Skip to content
Advertisement

OnBlur not closing the Listitems when clicked outside the Autocomplete

I am trying to implement an autocomplete component in react native. Everything works fine except for when I click outside the list still remains . onBlur() doesnt get triggered. I have Wrapped as suggested here by many but still it doesnt work.

Can someone please help me fix this ? Here is my code . Sorry for the long code.

import React, { Component } from "react";
import {
  FlatList,
  StyleSheet,
  Text,
  TextInput,
  View,
  TouchableOpacity,
  Keyboard,
  ScrollView,
} from "react-native";
import { Icon } from "react-native-elements";
// import SearchIcon from "../assets/Map/Search.svg";
export default class AutoCompleteBasics extends Component {
  constructor(props) {
    super(props);

    this.state = {
      text: "",
      textInputFocus: false,
      arrayList: [
        "Parcelle 1",
        "Parcelle 2",
        "Parcelle 3",
        "Parcelle 4",
        "Parcelle 5",
      ],
    };
  }

  updateDataWithKey = () => {
    const { arrayList } = this.state;
    const dataWithKey = arrayList.map((data) => {
      return { key: data };
    });
    this.setState({
      dataWithKey,
      filterData: dataWithKey,
    });
  };

  changeText = (text) => {
    this.setState({ text });
    const { dataWithKey } = this.state;
    if (text !== "") {
      let filterData = dataWithKey.filter((obj) => {
        return obj.key.toLowerCase().indexOf(text.trim().toLowerCase()) > -1;
      });
      if (filterData.length === 0) {
        filterData = [{ key: "No Filter Data" }];
      }
      this.setState({ filterData });
    } else {
      this.setState({ filterData: dataWithKey });
    }
  };

  hideKeyboard = () => {
    Keyboard.dismiss();
  };
  onListItemClicked = (text, index) => {
    const { onAutoCompleteClick } = this.props;
    onAutoCompleteClick(index);
    this.setState({
      text,
      textInputFocus: false,
      filterData: [{ key: text }],
    });
    this.handleInputBlur();
  };

  renderRow = (item, index) => {
    const { filterData } = this.state;
    return (
      <TouchableOpacity
        onPress={() => {
          this.hideKeyboard();
          this.onListItemClicked(item.key, index);
        }}
      >
        <Text style={styles.item}>{item.key}</Text>
      </TouchableOpacity>
    );
  };

  FlatListItemSeparator = () => {
    return (
      <View
        style={{
          height: 0.5,
          width: "100%",
          backgroundColor: "#2C2C2C",
        }}
      />
    );
  };
  handleInputFocus = () => {
    this.setState({ textInputFocus: true });
  };

  handleInputBlur = () => {
    this.setState({ textInputFocus: false });
  };

  render = () => {
    const { filterData, textInputFocus } = this.state;
    console.log("=====>", textInputFocus);
    return (
      <ScrollView keyboardShouldPersistTaps="handled" style={styles.container}>
        {/* <View> */}
        <View style={styles.innerContainer}>
          <TextInput
            style={styles.textInput}
            onFocus={() => this.handleInputFocus()}
            onBlur={() => this.handleInputBlur()}
            placeholder="Rechercher"
            placeholderTextColor="#d8d8d8"
            onChangeText={(text) => this.changeText(text)}
            value={this.state.text}
            onEndEditing={() => this.handleInputBlur()}
          />
          {/* {!textInputFocus && (
            <View style={{ left: -20 }}>
              <SearchIcon />
            </View>
          )} */}
        </View>
        {textInputFocus && (
          <FlatList
            ItemSeparatorComponent={this.FlatListItemSeparator}
            keyboardShouldPersistTaps="always"
            data={filterData}
            renderItem={({ item, index }) => this.renderRow(item, index)}
            style={{
              borderBottomLeftRadius: 25,
              borderBottomRightRadius: 25,
              backgroundColor: "#F2F2F2",
            }}
          />
        )}
        {/* </View> */}
      </ScrollView>
    );
  };
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    position: "absolute",
    top: 80,
    zIndex: 1,
    width: "60%",
    borderRadius: 25,
    // backgroundColor: "rgba(29, 29, 27, 0.5)",
    borderWidth: 2,
    borderColor: "#fff",
    borderStyle: "solid",
  },
  textInput: {
    color: "#F2F2F2",
    fontSize: 18,
    height: 40,
    width: "100%",
    marginTop: 8,
  },
  innerContainer: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    paddingLeft: 15,
    paddingRight: 15,
  },
  item: {
    padding: 10,
    paddingLeft: 20,
    fontSize: 18,
    height: 44,
    borderRadius: 25,
  },
});

Advertisement

Answer

The issue is some styles in container. Remove these from it:

position: "absolute",
width: "60%",
top: 80,

The top-level ScrollView should cover the screen, therefore keyboardShouldPersistTaps work as expected. Right now, it is not possible to tap on ScrollView outside of the input & Flatlist.

Advertisement