Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement @mention in TextInput

Tags:

How can I implement @mention in react native's TextInput?

I've tried this react-native-mention but it is not being maintained anymore. There are so many styling issues and callback issues.

What I want is to display custom view inside TextInput. Something like this.

Suggestionlist view

And after tapping on the list I want to display like this:

enter image description here

So far I am able to achieve:

When I type '@' in TextInput user list appear.

enter image description here

And when I tap on user I get username in TextInput

enter image description here

Code:

   renderSuggestionsRow() {
      return this.props.stackUsers.map((item, index) => {
         return (
            <TouchableOpacity key={`index-${index}`} onPress={() => this.onSuggestionTap(item.label)}>
               <View style={styles.suggestionsRowContainer}>
                  <View style={styles.userIconBox}>
                     <Text style={styles.usernameInitials}>{!!item.label && item.label.substring(0, 2).toUpperCase()}</Text>
                  </View>
                  <View style={styles.userDetailsBox}>
                     <Text style={styles.displayNameText}>{item.label}</Text>
                     <Text style={styles.usernameText}>@{item.label}</Text>
                  </View>
               </View>
            </TouchableOpacity>
         )
      });
   }

   onSuggestionTap(username) {
      this.setState({
         comment: this.state.comment.slice(0, this.state.comment.indexOf('@')) + '#'+username,
         active: false
      });
   }

   handleChatText(value) {
      if(value.includes('@')) {
         if(value.match(/@/g).length > 0) {
            this.setState({active: true});
         }
      } else {
         this.setState({active: false});
      }
      this.setState({comment: value});
   }
render() {
      const {comments} = this.state;
      return (
         <View style={styles.container}>
            {
               this.state.active ?
               <View style={{ marginLeft: 20}}>
                  {this.renderSuggestionsRow()}
               </View> : null
            }
            <View style={{ height: 55}}/>
            <View style={styles.inputContainer}>
               <TextInput
                  style={styles.inputChat}
                  onChangeText={(value) => this.handleChatText(value)}
               >
                  {comment}
               </TextInput>

               <TouchableOpacity style={styles.inputIcon} onPress={() => this.addComment()}>
                  <Icon type='FontAwesome' name='send-o' style={{fontSize: 16, color: '#FFF'}}/>
               </TouchableOpacity>
            </View>
         </View>
      );
   }
like image 736
Sagar Chavada Avatar asked Sep 15 '18 07:09

Sagar Chavada


People also ask

How do I validate TextInput in React Native?

You can validate your input value using onBlur event on TextInput You can apply your regex or check conditions on this event.

How do you Unfocus TextInput React Native?

To unfocus a TextInput in React Native, we can use the Keyboard. dismiss method. to set the onSubmitEditing prop to Keyboard. dismiss .


1 Answers

One simple solution would be to use react-native-parsed-text. Here is an example:

Example

import * as React from "react";
import { Text, View, StyleSheet } from 'react-native';
import ParsedText from 'react-native-parsed-text';

const userNameRegEx = new RegExp(/@([\w\d.\-_]+)?/g);
export default class Example extends React.Component {

  handleNamePress = (name) => {
    alert("Pressed username " + name);
  }

  render() {
    return (
      <View style={styles.container}>
        <ParsedText
          style={styles.text}
          parse={
            [
              {pattern: userNameRegEx, style: styles.username, onPress: this.handleNamePress},
            ]
          }
          childrenProps={{allowFontScaling: false}}
        >
          This is  a text with @someone mentioned!
        </ParsedText>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  text: {
    color: 'black',
    fontSize: 15,
  },
  username: {
    color: 'white',
    fontWeight: 'bold',
    backgroundColor: "purple",
    paddingHorizontal: 4,
    paddingBottom: 2,
    borderRadius: 4,
  },
});

However, this library doesn't support rendering custom views. The example above is achieved by just pure styling. If you need a custom view you need to implement something yourself. For a long time, it wasn't possible to render arbitrary components embedded inside a text-components. However, this has changed now afaik and we can do stuff like this:

<Text>Hello I am an example <View style={{ height: 25, width: 25, backgroundColor: "blue"}}></View> with an arbitrary view!</Text>

Example 2

Check both code examples here: https://snack.expo.io/@hannojg/restless-salsa

One important note: You can render the output of the ParsedText or your own custom component inside the TextInput, like this:

<TextInput
 ...
>
  <ParsedText
   ...
  >
    {inputValue}
  </ParsedText>
</TextInput>
like image 65
hannojg Avatar answered Sep 20 '22 19:09

hannojg