Hororo Sam
Hororo Sam

Reputation: 45

Handle Multiselect in a GridView

I'm trying to handle the multi-select with react-native-super-grid , here is my code :

<GridView
        itemDimension={80}
        items={items}
        style={styles.gridView}
        renderItem={item => ( 
            <View style={[styles.itemContainer , { backgroundColor:' transparent '}]}>
                <TouchableHighlight style={styles.buttonStyle} onPress={() => this.pressEvent() }> 
                  <Text> {item.image}</Text>   
               </TouchableHighlight>
               <Text style={styles.buttonText}> {item.name}</Text> 
          </View>)}
        />

I tried using this function :

    pressEvent(arr){

    if(this.state.pressStatus == false){
      this.setState({ pressStatus: true})  
      this.state.arr.push(arr)
      this.setState({ color : 'white'})
    } else {
      this.setState({ pressStatus: false})
      this.setState({ color: 'red'})
    } 
  }

but it somehow doesn't work , can someone help me ?

Thank you .

Upvotes: 0

Views: 766

Answers (2)

Shehryar Raza
Shehryar Raza

Reputation: 1

Since GridView has been merged into FlatGrid. Therefore, I've implemented the multi-select option in a pretty easy way. First of all I applied TouchableOpacity on top of the view in the renderItems prop of FlatGrid like this.

 <TouchableOpacity
        onPress={() => this.selectedServices(item.name)}>
...props
</TouchableOpacity>

SelectedServices:

selectedServices = item => {
let services = this.state.selectedServices;

if (services.includes(item) == false) {
  services.push(item);
  this.setState({ selectedServices: services });

} else {
  let itemIndex = services.indexOf(item);
  services.splice(itemIndex, 1);
  this.setState({ selectedServices: services });

}

};

Using splice, indexOf, and push, you can easily implement multi-selection.

To change the backgroundColor of the currently selected item, you can apply a check on the backgroundColor prop of the view.

renderItem={({ item, index }) => (
      <TouchableOpacity

        onPress={() => this.selectedServices(item.name)}
      >
        <View
          style={[
            styles.itemContainer,
            {
              backgroundColor: this.state.selectedServices.includes(
                item.name
              )
                ? '#0052cc'
                : item.code
            }
          ]}
        >
          <Text style={styles.itemName}>{item.name}</Text>
        </View>
      </TouchableOpacity>
    )}

Upvotes: 0

parohy
parohy

Reputation: 2180

This short example should give you an idea what are you doing wrong. The items itself are not aware of the state. So what I would do, I would create a separate child component for grid item and handle press state locally. Then handle parent, which is holding all the item trough callback about the pressed item.

class MyGridView extends Component {
render() {
    return (
        <GridView
            itemDimension={80}
            items={items}
            style={styles.gridView}
            renderItem={item => (
                <GridItem
                    item={item}
                    onItemPress={selected => {
                        // set grid view callback
                        if (selected) {
                            //if true add to array
                            this.addToPressedArray(item);
                        } else {
                            //false remove from array
                            this.removeFromPressedArray(item);
                        }
                    }}
                />
            )}
        />
    );
}

// You don't change the state directly, you mutate it trough set state
addToPressedArray = item => this.setState(prevState => ({ arr: [...prevState.arr, item] }));

removeFromPressedArray = item => {
    const arr = this.state.arr.remove(item);
    this.setState({ arr });
};
}

And the GridItem

class GridItem extends Component {
// starting local state
state = {
    pressStatus: false,
    color: 'red'
};

// handle on item press
pressEvent = () => {
    this.setState(prevState => ({
        pressStatus: !prevState.pressStatus, //negate previous on state value
        color: !prevState.pressStatus ? 'white' : 'red' //choose corect collor based on pressedStatus
    }));

    // call parent callback to notify grid view of item select/deselect
    this.props.onItemPress(this.state.pressStatus);
};

render() {
    return (
        <View style={[styles.itemContainer, { backgroundColor: ' transparent ' }]}>
            <TouchableHighlight style={styles.buttonStyle} onPress={() => this.pressEvent()}>
                <Text> {item.image}</Text>
            </TouchableHighlight>
            <Text style={styles.buttonText}> {item.name}</Text>
        </View>
    );
}
}

I also recommend to read about React.Component lifecycle. Its a good reading and gives you a better understanding how to achieve updates.

Upvotes: 2

Related Questions