2

I have a structure in json this way (I can not change the data in this json):

 itens: {"countcats":2,"countsubcats":7,
 "catsubcatsdata":{
 "15978738e6cd1e":{"title":"Test 1","description":"blablabla",
 "subcats":{
 "1597873b1653d9": {"codurl":"t01url","title":"Teste subiten 1","description":""},
 "1597873bd76c80": {"codurl":"t01url2","title":"Testing sub two","description":""},
 "1597873c9d4a81": {"codurl":"t01url3","title":"Test sub 3","description":"blablabla 01"},
 }},
 "15978745b32c1b":{"title":"Loren Ipsun","description":"lamet dectoid samet",
 "subcats":{
 "159787464bc887":{"codurl":"maecenas","title":"Maecenas pulvinar","description":"orci non volutpat varius"},
 "159787472eb5e6":{"codurl":"donecorci ","title":"Donec hendrerit orci","description":""},
 "15978748b89bca":{"codurl":"massadictum","title":"Nullam eu massa dictum", "description":""},
 "159787495492f4":{"codurl":"ultricies","title":"Etiam massa arcu","description":"Donec ultricies porttitor augue quis dictum. Quisque efficitur nec sapien eu ultricies"}
 }}
 }}

I have the following code:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="v-for-sectors">
	<input type="text" placeholder="Search" v-model="searchQuery">
 <ul>
 <li v-for="(value, key) in filteredList">
 <b>{{ value.title }}</b><br>{{ value.description }}
			<ul>
			 <li v-for="(vsub, keysub) in value.subcats"><a v-bind:href="'http://www.teste.com/'+vsub.codurl">{{ vsub.title }} - {{ vsub.description }}</a></li>
			</ul>
 </li>
 </ul>
</div>
<script>
 new Vue({
 el: '#v-for-sectors',
 data: {
 searchQuery: '',
 itens: {"catsubcatsdata":{"15978738e6cd1e":{"title":"Test 1","description":"blablabla","subcats":{"1597873b1653d9":{"codurl":"t01url","title":"Teste subiten 1","description":""},"1597873bd76c80":{"codurl":"t01url2","title":"Testing sub two","description":""},"1597873c9d4a81":{"codurl":"t01url3","title":"Test sub 3","description":"blablabla 01"}}},"15978745b32c1b":{"title":"Loren Ipsun","description":"lamet dectoid samet","subcats":{"159787464bc887":{"codurl":"maecenas","title":"Maecenas pulvinar","description":"orci non volutpat varius"},"159787472eb5e6":{"codurl":"donecorci","title":"Donec hendrerit orci","description":""},"15978748b89bca":{"codurl":"massadictum","title":"Nullam eu massa dictum","description":""},"159787495492f4":{"codurl":"ultricies","title":"Etiam massa arcu","description":"Donec ultricies porttitor augue quis dictum."}}}}}
		},
 computed: {
 filteredList: function () {
 var filterKey = this.searchQuery && this.searchQuery.toLowerCase()
 var data = this.itens.catsubcatsdata
 var dataarray = Object.keys(data)
 
 if (!filterKey) { return data; }
 
 return dataarray
 .filter(function(key) {
 var row = data[key];
 return Object.keys(row)
 .some(function(key) {
 return String(row[key])
 .toLowerCase()
 .indexOf(filterKey) > -1;
 })
 })
 .reduce(function(acc, key) {
 acc[key] = data[key];
 return acc;
 }, {})
 }
 }
 });
</script>

I would like it when typing in the search something about the title or description of the category displaying something like this:

(This is already working.)

enter image description here

But when the word was from the title or description of a subcategory, it should show:

(This is not working.)

enter image description here

Can anyone help me on how to make this work?

asked Feb 19, 2019 at 22:34
6
  • I noticed that all of your data is contained in objects instead of arrays. That will make your life miserable, as the array manipulation functions (map, filter, reduce) will not work with objects. Commented Feb 19, 2019 at 22:36
  • @James Yes, and unfortunately I can not change the data received in json. :( Commented Feb 19, 2019 at 22:38
  • @James But if it was in array do you have an idea of ​​how it could be done? Maybe it helps me get an idea of ​​how to convert to object. Commented Feb 19, 2019 at 22:40
  • @James Maybe in PHP I can handle json and change it to a way that works easier, but I do not know how it should be. If you can help me with any answer, maybe I can find a way. Commented Feb 19, 2019 at 22:42
  • Stay with object data type would easier to access & manipulate the node data. You can still loop through object's props and do filter it right? It's not relate to Vuejs. Commented Feb 20, 2019 at 2:39

1 Answer 1

2

As I understand it, you want to filter by your search term, including the entire entry for any that match title or description in the top-level, or including the top-level and only matching sub-levels that match if the match is in a sub-level and not in the top level.

So first I made a method matches so that code isn't messy. Then I made a computed to return the values of interest as a list. Then I made a computed to filter those values based on the criteria above, constructing a new object with only matching subcats when that was where the match was.

new Vue({
 el: '#v-for-sectors',
 data: {
 searchQuery: '',
 itens: {
 "catsubcatsdata": {
 "15978738e6cd1e": {
 "title": "Test 1",
 "description": "blablabla",
 "subcats": {
 "1597873b1653d9": {
 "codurl": "t01url",
 "title": "Teste subiten 1",
 "description": ""
 },
 "1597873bd76c80": {
 "codurl": "t01url2",
 "title": "Testing sub two",
 "description": ""
 },
 "1597873c9d4a81": {
 "codurl": "t01url3",
 "title": "Test sub 3",
 "description": "blablabla 01"
 }
 }
 },
 "15978745b32c1b": {
 "title": "Loren Ipsun",
 "description": "lamet dectoid samet",
 "subcats": {
 "159787464bc887": {
 "codurl": "maecenas",
 "title": "Maecenas pulvinar",
 "description": "orci non volutpat varius"
 },
 "159787472eb5e6": {
 "codurl": "donecorci",
 "title": "Donec hendrerit orci",
 "description": ""
 },
 "15978748b89bca": {
 "codurl": "massadictum",
 "title": "Nullam eu massa dictum",
 "description": ""
 },
 "159787495492f4": {
 "codurl": "ultricies",
 "title": "Etiam massa arcu",
 "description": "Donec ultricies porttitor augue quis dictum."
 }
 }
 }
 }
 }
 },
 methods: {
 matches(obj) {
 const term = this.searchQuery.toLowerCase();
 return obj.title.toLowerCase().includes(term) || obj.description.toLowerCase().includes(term);
 }
 },
 computed: {
 listValues() {
 return Object.values(this.itens.catsubcatsdata);
 },
 filteredList() {
 if (!this.searchQuery) {
 return this.listValues;
 }
 return this.listValues
 .map((v) => {
 if (this.matches(v)) {
 return v;
 }
 const matchingSubcats = Object.values(v.subcats)
 .filter((v) => this.matches(v));
 
 if (matchingSubcats.length > 0) {
 return Object.assign({}, v, {subcats: matchingSubcats});
 }
 })
 .filter((v) => v);
 }
 }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="v-for-sectors">
 <input type="text" placeholder="Search" v-model="searchQuery">
 <ul>
 <li v-for="value in filteredList">
 <b>{{ value.title }}</b><br>{{ value.description }}
 <ul>
 <li v-for="(vsub, keysub) in value.subcats"><a v-bind:href="'http://www.teste.com/'+vsub.codurl">{{ vsub.title }} - {{ vsub.description }}</a></li>
 </ul>
 </li>
 </ul>
</div>

answered Feb 20, 2019 at 2:16

1 Comment

Genius, Thank you. The only thing, thats ended up missing the key code, this is very important to me. But I managed to solve by manipulating json with php. Your code worked perfectly.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.