简体   繁体   中英

How to filter nested objects? ReactJS

Data sample:

nodes:[
        {
        label:"Egor1",
        value:"Egor1",
        restorePoint:"25/10/2017 10:00:29 PM",
        vmcount:"2",
        restorePointsCount:"",
        children:[
          {label:"disk111111111111111",
          value:"disk1",
          restorePoint:"3 days ago",
          vmcount:"",
          restorePointsCount:"11",
        },
        {label:"disk22222222222222",
        value:"disk2",
        name:"jobname2",
        restorePoint:"4 days ago",
        vmcount:"",
        restorePointsCount:"11"},
        {label:"disk555",
        value:"disk552",
        name:"jobnam555e2",
        restorePoint:"4 days ago",
        vmcount:"",
        restorePointsCount:"11"}
      ]}
      ,

      {
        label:"Egor12",
        value:"Egor12",
        restorePoint:"25/10/2017 10:00:29 PM",
        vmcount:"22",
        restorePointsCount:"",
        children:[
          {label:"disk111111111111111",
          value:"disk1",
          restorePoint:"2 days ago",
          vmcount:"",
          restorePointsCount:"12",
        },
        {label:"disk22222222222222",
        value:"disk2",
        name:"jobname2",
        restorePoint:"restorepoint4",
        vmcount:"",
        restorePointsCount:"12",}
      ]},


      ],

Try to do next:

filter(e) {
    var value = e.target.value;
    this.setState({filterval: value})
    this.setState({
      filteredItems: !value
        ? false
        : this.state.nodes.filter(function (item) {
          return 
          item.children.value.toLowerCase().indexOf(value.toLowerCase()) !== -1;
        })
    })
  }

But filter wants work, how filter by nested objects? Can't find any exmaple. it possible to do with _lodash?

For example I search label:"disk111111111111111

In result must be array like this :

{
        label:"Egor1",
        value:"Egor1",
        restorePoint:"25/10/2017 10:00:29 PM",
        vmcount:"2",
        restorePointsCount:"",
        children:[
          {label:"disk111111111111111",
          value:"disk1",
          restorePoint:"3 days ago",
          vmcount:"",
          restorePointsCount:"11",
        },

So it must return not only elements, that I search, it must return childrens with parents.

Your item.children is an array. If there is only one item in it, then you can do item.children[0] . Otherwise, you have to loop it too to check your condition.

You can mix map and filter . First one maps every item and filter its children (according your needs) and the second one filters items which has children.length > 0

 const nodes = [ { label: 'Egor1', value: 'Egor1', restorePoint: '25/10/2017 10:00:29 PM', vmcount: '2', restorePointsCount: '', children: [ { label: 'disk111111111111111', value: 'disk1', restorePoint: '3 days ago', vmcount: '', restorePointsCount: '11', }, { label: 'disk22222222222222', value: 'disk2', name: 'jobname2', restorePoint: '4 days ago', vmcount: '', restorePointsCount: '11', }, { label: 'disk555', value: 'disk552', name: 'jobnam555e2', restorePoint: '4 days ago', vmcount: '', restorePointsCount: '11', }, ], }, { label: 'Egor12', value: 'Egor12', restorePoint: '25/10/2017 10:00:29 PM', vmcount: '22', restorePointsCount: '', children: [ { label: 'disk111111111111111', value: 'disk1', restorePoint: '2 days ago', vmcount: '', restorePointsCount: '12', }, { label: 'disk22222222222222', value: 'disk2', name: 'jobname2', restorePoint: 'restorepoint4', vmcount: '', restorePointsCount: '12', }, ], }, ] const value = 'disk552' const result = nodes .map(item => ({ ...item, children: item.children .filter(child => child.value.includes(value.toLowerCase())) })) .filter(item => item.children.length > 0) console.log(result) 

You could filter over the nodes then test the children.value to see which nodes to keep.

 const FakeReact = { setState(newState) { this.state = Object.assign({}, this.state, newState) }, state: { nodes: [ { value: "Egor1", children: [{ value: "disk1" }, { value: "disk2" }] }, { value: "Egor2", children: [{ value: "disk3" }, { value: "disk4" }] }, ] } } const fakeEvent = { target: { value: 'disk1' }} function filter(e) { const value = e.target.value; const regex = new RegExp('.*' + value + '.*', 'gi') this.setState({ filterval: value, // may as well only make one call to set state filteredItems: (!value) ? [] // try to keep the same type for the false value : this.state.nodes.filter( // filter the node node => node.children.find( // check if the child value matches the input value // if it does the node will be returned to filteredItems child => regex.test(child.value) ) ) }) } // call filter with the FakeReact as the context and a fake event filter.call(FakeReact, fakeEvent) console.log('nodes', FakeReact.state.nodes) console.log('filteredItems', FakeReact.state.filteredItems) 
 <script src="https://codepen.io/synthet1c/pen/KyQQmL.js?theme=onedark"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM