simaAttar
simaAttar

Reputation: 507

How to highlight search results in React-Native FlatList?

I'm newbie in React-native. I need to highlight the search results in my FlatList while I'm typing in search bar. There are 2 componenrs: react-native-highlight-words and react-native-text-highlight , But I cant figure out how to make use of them! here is my code:

import React, { Component } from 'react';
import {StyleSheet, Text, View, FlatList, TouchableOpacity } from 'react-native';
import { List, ListItem, SearchBar } from 'react-native-elements';
import DropdownMenu from 'react-native-dropdown-menu';
import {Header, Left, Right, Icon} from 'native-base'

var SQLite = require('react-native-sqlite-storage')
var db = SQLite.openDatabase({name: 'test.sqlite', createFromLocation: '~dictionary.sqlite'})
var data = [["English", "Arabic", "Persian"]];

export default class App extends Component {
  constructor(props) {
    super(props)
    this.state = {record: [], arrayholder : [], query:''};
    db.transaction((tx) => {
      tx.executeSql('SELECT * FROM tblWord', [], (tx, results) => {
          let row = results.rows.item();
          arrayholder = results.rows.raw()
          record = results.rows.raw()
          this.setState({arrayholder: arrayholder})
          this.setState({ record: record })
          }});});  
      }

  searchFilterFunction = text => {
    var newData = this.state.arrayholder;
    newData = this.state.arrayholder.filter(item => {
      const itemData = item.word_english.toLowerCase()
      const textData = text.toLowerCase()
      return itemData.indexOf(textData) > -1 });
    this.setState({query: text,record: newData });
  };


  render() {
    return (
      <View style = {styles.container}>
        <Header style={styles.headerStyle}>
            ...
        </Header>
        <View style={styles.menuView}>
          <DropdownMenu
            bgColor={"#B38687"}
            activityTintColor={'green'}
            titleStyle={{color: '#333333'}} 
            handler={(selection, row) => this.setState({text4: data[selection][row]})}
            data={data}
            >
          </DropdownMenu>
        </View >
        <View >
          <View style={styles.searchBarView}>
            <SearchBar
              placeholder="Search"
              lightTheme
              value = {this.state.query}
              onChangeText={text => this.searchFilterFunction(text)}
              autoCorrect={false}
              inputStyle={{backgroundColor: 'white'}}
              containerStyle={{backgroundColor: 'white', borderWidth: 1, borderColor:'#B38687', }}
              />
          </View>

          <View style={styles.flatListVew}>
            <List containerStyle={{ flexDirection: 'column-reverse', borderTopWidth: 0, borderBottomWidth: 0 }} >
              <FlatList 
                data={this.state.record} 
                keyExtractor={((item, index) => "itemNo-" + index)}
                renderItem={({item}) => (
                  <ListItem
                    roundAvatar
                    onPress={() => {this.props.navigation.navigate('Screen2', {data: (item.word_english +'\n' + item.word_arabic)} ); }}
                    title={item.word_english}
                    containerStyle={{ borderBottomWidth: 0 }}
                  /> )}
                />
              </List>
            </View>
          </View>
       </View>);}
          }

const styles = StyleSheet.create({
 ...

I want the results to look like this:

enter image description here

Any help would be greatly appreciated.

Upvotes: 4

Views: 5576

Answers (4)

Engr.Aftab Ufaq
Engr.Aftab Ufaq

Reputation: 6272

Here is an example

import React from 'react';
import { View } from 'react-native';
import { moderateScale } from 'react-native-size-matters';
import HighlightText from './src/components/HighlightText';
import theme from './src/constants/theme';


    const App = () => {
      return (
        <View
          style={{
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: theme.whiteColor,
            paddingHorizontal:moderateScale(40)
          }}>
          <HighlightText searchText={"you"} text={"Sometimes in life, life can throw unexpected surprises at you. You might find yourself wondering if you're really making progress, progress that leads you to your dreams. Dreams can be elusive, but they're what keep you going, going forward even when you face obstacles. Obstacles may seem insurmountable, but you have the strength, strength deep within you, to overcome them. So, remember to stay true to yourself, yourself, and keep pursuing your dreams with passion and determination."}  />
        </View>
      );
    };
    export default App;

The highlight component is here .

import React from 'react';
import { Text } from 'react-native';
import fonts from '../constants/fonts';
import { moderateScale } from '../constants/scaling';
import theme from '../constants/theme';
const HighlightText = ({searchText, text}) => {
  //const escapedSearchText = searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
  const regex = new RegExp(`(${searchText})`, 'gi');
  const parts = text.split(regex);
  
  return (
    <Text>
      {parts.map((part, i) => {
        console.log('====================================');
        console.log(part.toLowerCase() == searchText.toLowerCase());
        console.log('====================================');
        return (
          <Text
            key={i}
            style={
              part.toLowerCase() == searchText.toLowerCase()
                ? {
                    fontSize: moderateScale(14),
                    fontFamily: fonts.Bold,
                    color: theme.primaryColor,
                    includeFontPadding: false,
                  }
                : {
                    color: theme.textColor,
                    fontSize: moderateScale(14),
                    includeFontPadding: false,
                    fontFamily: fonts.Bold,
                  }
            }>
            {part}
          </Text>
        );
      })}
    </Text>
  );
};

export default HighlightText;

Upvotes: -1

Redmen Ishab
Redmen Ishab

Reputation: 2349

 handleChangeText = param => {
const {categoryList} = this.state;
const regEx = "\\s*(" + param + ")\\s*"
const validator = new RegExp(regEx, 'i');
let filterData = [];
//here is categorylist is the data supplied to flatlist.
categoryList.forEach(item => {
  let flag = validator.test(item.teamtype);
  if (flag) {
    //here set the highlighting color
  }
})

};

Call the above function onChangeText() of your search field.

Upvotes: 0

Rocky
Rocky

Reputation: 3235

You can pass text or custom view to ListItem component as props for title. I am using React Native Highlight Words to highlight text as you stated.

add React Native Highlight Words by add the below line:

import Highlighter from 'react-native-highlight-words';

Update code for ListItem component for desired result:

<ListItem
    roundAvatar
    onPress={() => {this.props.navigation.navigate('Screen2', {data: (item.word_english +'\n' + item.word_arabic)} ); }}
    title={
      <Highlighter
          highlightStyle={{backgroundColor: 'yellow'}}
          searchWords={[this.state.query]}
          textToHighlight={item.word_english}
      />}
    containerStyle={{ borderBottomWidth: 0 }}
/>

Upvotes: 4

J. Hesters
J. Hesters

Reputation: 14766

You can highlight using your own styles.

Here is a simple example:

const myList = [{ text: 'Hi', id: 1 }, ... ]

class List extends Component {
  this.state = { highlightedId: undefined }

  render() {
    return (
        <FlatList
        data={myList}
        renderItem={({item}) => <Text style={item.id === this.state.highlightedId ? styles.hightlighted : undefined}>{item.text}</Text>}
      />
    )
  }
}

const styles = StyleSheet.create({
  highlighted: {
    backgroundColor: "yellow"
  }
})

In your case you can adjust the containerStyle of the <ListItem />.

Upvotes: 0

Related Questions