Tanveerbyn
Tanveerbyn

Reputation: 784

How to select multiple values in flatlist based on there key

I'm using react native's powerful flatlist this is my array which is like this:

data =   [
      {Color:[{'label':'BLUE','value':'10'}, {'label':'RED','value':'11'}]},
      {Size:[{'label':'SMALL','value':'13'},{'label':'BIG','value':'12'}]}
      ]

and here it Is my flatlist

<FlatList data={data}
              numColumns={1}
              keyExtractor={(item, index) => index.toString()}
              extraData={this.state}
              ItemSeparatorComponent={FlatListItemSeparator}
              renderItem={({item, index}) => {
                return(
                <View >
                <Text >{Object.keys(item)}</Text>
                <FlatList data={item[Object.keys(item)]}
                numColumns={5}
                keyExtractor={(index) => "D"+index.toString()}
                extraData={this.state}
                renderItem={({item, index}) => {
                  return(
                        <TouchableOpacity onPress={() => this._handleclick(index, item)} style={[
                            styles.Buttoncolor, this.state.selected == index+item.label
                              ? styles.onfocusbutton
                              : null
                          ]}>
                          <Text style={[styles.textcolor,this.state.selected == index+item.label?styles.white:null]}>{item.label}</Text>
                        </TouchableOpacity>
                        )
                }
                }/>
              </View>)}}/>

this is the function where im matching the index of item..

  _handleclick = (index, item) => {
        this.setState({selected: index+item.label, selectedColor: item.value})
      }

here it is what I tried :->

I call hand click function match its value with index+label name and it get change itself but when I click on BLUE it change its color but when I click on SMALL it can change itself but blue gets its previous condition

now here's main what I want to do :->

I want to select only one item based on there array which is 'Color' I want that when I click on BLUE it can be change it color . and if I click also on SMALL it can also change color itself that two value need to be stored.

I hope you could easily understand. thanks in advance

UPDATE 1

STATUS :SOLVED

Changes

_handleclick = (index, item,objectname) => {
         const {selected,result} = this.state
         let selectedIndex = this.state.selected.indexOf(item.value);
            if(selectedIndex == -1){
           let my =   this.state.result.filter((e)=>{return e[objectname]})
             selected.forEach((items) => {
                    let arrayofattribute =   result.filter((e)=>{return e[objectname]})
                    arrayofattribute.forEach((value,index)=>{
                    newval =  value[objectname].map((val,i)=>{
                        if(items == val.label)
                        {
                          selected.splice(selected.indexOf(val.label),1)
                        }
                      })
                    })
             })
            this.setState({selected:[item.label,...this.state.selected]})
          }
      }

in Flatlist render

<TouchableOpacity
                        onPress={() => this._handleCategoryColor(index, item,objectname)}

                        style={[
                          styles.Buttoncolor,

                          this.state.selected.indexOf(item.label) != -1
                            ? styles.onfocusbutton
                            : null,
                        ]}>
                        <Text
                          style={[
                            styles.textcolor,
                            this.state.selected.indexOf(item.label) != -1
                              ? styles.white
                              : null,
                          ]}>
                          {item.label}

                        </Text>
                      </TouchableOpacity>

Upvotes: 1

Views: 4089

Answers (3)

Milore
Milore

Reputation: 1672

If I correcty understood you need to select just one option for each property (colors and sizes). So you need to have a field in your state for each element you want to be saved.

Your _handleClick function could be something like this:

_handleclick = (index, item) => {
  const { Color } = this.state.data[0];
  const { Size } = this.state.data[1];
  this.setState(state => ({
    selectedColor: Color.find(color => color.label === item.label)
      ? index + item.label
      : state.selectedColor,
    selectedSize: Size.find(size => size.label === item.label)
      ? index + item.label
      : state.selectedSize,
  }));
};

Every time you click on an element you need to know if it's a color or a size and then correctly update the right field. Maybe this is not the most performant way, but it works.

Then, in your render method, in order to assign style you could check both conditions:

<TouchableOpacity
  onPress={() => this._handleclick(index, item)}
  style={[
    styles.Buttoncolor,
    this.state.selectedSize == index + item.label ||
    this.state.selectedColor == index + item.label
      ? styles.onfocusbutton
      : null,
  ]}>
  <Text
    style={[
      styles.textcolor,
      this.state.selectedSize == index + item.label ||
      this.state.selectedColor == index + item.label
        ? styles.white
        : null,
    ]}>
    {item.label}
  </Text>
</TouchableOpacity>

I tried to reproduce your question in this snack, you can take a look.

Upvotes: 1

Subhendu Kundu
Subhendu Kundu

Reputation: 3856

Probably the issue is with the function arguments assignments. If you see both renderItem methods in Flatlist uses renderItem={({item, index}) so the last renderItem can access the above item, index. There's an confusion when onPress called, which item or index to put in the callback. Please try to add the arg different names. Like

<FlatList data={data}
   numColumns={1}
   keyExtractor={(item, index) => index.toString()}
   extraData={this.state}
   ItemSeparatorComponent={FlatListItemSeparator}
   renderItem={({item, index}) => {
   return(
     <View >
     <Text >{Object.keys(item)}</Text>
     <FlatList data={item[Object.keys(item)]}
                numColumns={5}
                keyExtractor={(index) => "D"+index.toString()}
                extraData={this.state}
                renderItem={({set, key}) => {
                  return(
                        <TouchableOpacity onPress={() => this._handleclick(key, set)} style={[
                            styles.Buttoncolor, this.state.selected == index+item.label
                              ? styles.onfocusbutton
                              : null
                          ]}>
                          <Text style={[styles.textcolor,this.state.selected == index+item.label?styles.white:null]}>{item.label}</Text>
                        </TouchableOpacity>
                        )
                }
                }/>
              </View>)}}/>

Let me know if this fixes your issue. Happy coding. :)

Upvotes: 1

Jaydeep Galani
Jaydeep Galani

Reputation: 4961

you can try array instead of storing single selected item,

make selected state as empty array when you are declaring.

...
<TouchableOpacity onPress={() => this._handleclick(index, item)} style={[
                            styles.Buttoncolor, this.state.selected.indexOf(index+item.label) != -1
                              ? styles.onfocusbutton
                              : null
]}>
    <Text style={[styles.textcolor, this.state.selected.indexOf(index+item.label) != -1?styles.white:null]}>{item.label}</Text>
</TouchableOpacity>

here is you handle method, push new selected item to selected array

_handleclick = (index, item) => {
        let selectedIndex = this.state.selected.indexOf(index+item.label);
        if(selectedIndex== -1){
          this.setState({selected: [...this.state.selected,index+item.label], selectedColor: item.value})
        }

      }

Upvotes: 1

Related Questions