0

I want to loop through a JSON Array to search for a keyword. I am refering this thread to achieve this.

entries is a JSON array of stucture

[
    {"a": "something", "id": 54785, "b": ["each", "every", "one"]},
    {"a": "something", "id": 54785, "b": ["each", "every", "one"]},
    {"a": "something", "id": 54785, "b": ["each", "every", "one"]},
]

searchItem came from this custom component

<FormInput type="text"
    v-model="searchItem"
    @input="searchObject()"
    placeholder="Search here">
</FormInput> 

I placed my function in methods of component like this.

searchObject: function() {
  for (var i=0; i<this.entries.length; i++) {
    for (var key in this.entries[i]) {
      if (this.entries[i].key.indexOf(this.searchItem)!==-1) {
        this.result.push(this.entries[i])
      }
    }
  }
  return this.result
}

I get this error in console

TypeError: Cannot read property 'indexOf' of undefined

When I change in computed function and try [key] instead of .key

searchObject() {
  for (var i=0; i<this.entries.length; i++) {
    for (var key in this.entries[i]) {
      if (this.entries[i][key].indexOf(this.searchItem)!==-1) {
        this.result.push(this.entries[i])
      }
    }
  }
  return this.result
}

I am not getting anything pushed in result, neither I am getting any error in console. I tried to put console.log() command on my function, but again nothing on console.

halfer
  • 19,824
  • 17
  • 99
  • 186
f1uk3r
  • 317
  • 7
  • 15

2 Answers2

2

Assuming that each object doesn't have any deeply nested objects or arrays inside it, you can use Object.values to get the values of your object.

With your current data, the returned values will contain another array so you have to flatten it by using .concat.apply to merge the values into one array.

Using the flattened array, you can then easily check if the current object contains your searchItem.

Edit: If you want to include an item to the result if the searchItem matches certain parts of the item values, you can use .join to concatenate your flattened values into a string.

See example below:

var app = new Vue({
  el: '#app',
  data: {
    result: [],
    searchItem: '',
    entries: [{
        "a": "something",
        "id": 54785,
        "b": ["one", "two", "three"]
      },
      {
        "a": "nothing",
        "id": 54785,
        "b": ["each", "every", "one"]
      },
      {
        "a": "everything",
        "id": 54785,
        "b": ["each", "every", "one"]
      },
    ]
  },
  methods: {
    searchObject: function() {
      this.result = []; // clear data, for demonstration only, remove if not needed

      for (var i = 0; i < this.entries.length; i++) {
        var values = [].concat.apply([], this.getValues(this.entries[i]));
        
        // you can also convert it to a string to match certain string parts
        values = values.join(',');
        
        if (values.indexOf(this.searchItem) !== -1) {
          this.result.push(this.entries[i])
        }
      }
    },
    getValues: function(object) {
      // use a polyfill in case Object.values is not supported by current browser
      return Object.values ? Object.values(object) : Object.keys(object).map(key => object[key]);
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<div id="app">
  <input type="text" v-model="searchItem" v-on:input="searchObject" placeholder="Search here" />
  <ul>
    <li v-for="i in result">{{i}}</li>
  </ul>
</div>
Ana Liza Pandac
  • 4,795
  • 2
  • 24
  • 36
0

here is simple demo :

var app = new Vue({
  el: '#app',
  data: {
    result:[],
    searchItem:'',
    entries:
     [
{"a": "something", "id": 54785, "b": ["each", "every", "one"]},
{"a": "something", "id": 54785, "b": ["each", "every", "one"]},
{"a": "something", "id": 54785, "b": ["each", "every", "one"]},
]
  },methods:{
    searchObject:function(){
       for (var i=0; i<this.entries.length; i++) {
        for (var key in this.entries[i]) {
            if (key.indexOf(this.searchItem)!==-1) {
            this.result.push(this.entries[i])
            }
        }
      }
      if(this.searchItem && this.searchItem.length>0){
        return this.result;      
      }else{
         return this.result=[];
      }
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<div id="app">
  <input
type="text"
v-model="searchItem"
v-on:input="searchObject"
placeholder="Search here" />
<p>{{'searchItem :'+searchItem}}</p>
<ul>
<li v-for="i in result">{{i}}</li>
</ul>
</div>
Saurabh Mistry
  • 12,833
  • 5
  • 50
  • 71