vue cannot acces object props - vue.js

i do a find method in an array to search for the object. I get back the object, but i can't acces the props in that object. The nuxt error thrower says the following:
Cannot read property 'value' of undefined
my code:
<v-data-table :headers="datatable.headers" :items="datatable.items" class="elevation-1">
<template v-slot:body="{ items }">
<tr v-show="inMenu.find(menuItem => menuItem.name == item.name.toLowerCase()).value == true" v-for="(item, index) in items" :key="index">
<td>{{item.name}}</td>
<!-- problem is in the <v-text-field> v-model -->
<td><v-text-field v-model="settings.adminIcons.find(menuItem => menuItem.key == item.name.toLowerCase()).value" label="icon"></v-text-field></td>
</tr>
</template>
</v-data-table>
the weird thing is, that if i do this:
<!-- works -->
<v-text-field v-model="settings.adminIcons.find(menuItem => menuItem.key == 'evenementen').value" label="icon">
instead of this:
<!-- does not work -->
<!-- item.name.toLowerCase() == 'evenementen' -->
<v-text-field v-model="settings.adminIcons.find(menuItem => menuItem.key == item.name.toLowerCase()).value" label="icon">
it will not work. but item.name.toLowerCase() is the same as 'evenementen'.
any solution?

It's giving error because in find it doesn't find any single item its return noting and you are trying to access .value.
// Error
//console.log(settings['adminIcons'].find(menuItem => menuItem.key == "env1").value)
<script>
const array1 = [5, 12, 8, 130, 44];
const settings = {
'adminIcons':[
{"key":"env",
"value":"value1"}
]
}
const found = array1.find(element => element > 10);
console.log(settings['adminIcons'].find(menuItem => menuItem.key == "env").value);
// Error
//console.log(settings['adminIcons'].find(menuItem => menuItem.key == "env1").value);
</script>

Basically, you are accessing the value of item where item is not available in your data model.
This code will give you a string and this is where your error came from
menuItem.key == item.name.toLowerCase()) // if item.name = 'Test' will become 'test'.
Now, the returned of it it is not already the item you are accessing in your loop originally, rather give you a result but in new data. That's why when you are accessing it's value it say's that cannot read property value of undefined.

Related

Quasar q-select display nothing when I choose one of the options

New to Quasar, and I try to create a q-select that getting as options a list of objects. So far, I achieved to display the options in the dropdown, but when I select an element, the q-select remains empty although the page component data value is filled properly.
See the following git for more info:
My q-select implementation is like this:
<template>
<!-- ... -->
<q-select
v-model="parentCategory"
clearable
use-input
input-debounce="350"
label="Parent Category"
:options="businessCategoriesToSelect"
:option-label="opt => Object(opt) === opt && 'title' in opt ? opt.title : null"
:option-value="opt => Object(opt) === opt && '#id' in opt ? opt['#id'] : null"
:display-value="Object(parentCategory) === parentCategory && 'title' in parentCategory ? parentCategory.title : null"
emit-value
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No Business Categories Found
</q-item-section>
</q-item>
</template>
</q-select>
<!-- ... -->
</template>
<script>
// ...
export default {
// ...
data() {
return {
// ...
parentCategory : null,
// ...
businessCategoriesToSelect: [],
// ...
};
},
// ...
}
</script>
The objects loaded in the businessCategoriesToSelect have the following form:
And when I select one of the options in the q-select item the data property that is responsible to hold the selected value it has a value like this:
But although all seems to be OK with what I did, the q-select still don't like to display the proper value.
Any idea on how to solve that issue?
I answer to my self just to provide my solution in order to help any other person has the same problem with me.
Finally I solved the problem by using the slot selected-item. The final solution is like that:
<q-select
v-model="parentCategory"
clearable
use-input
input-debounce="350"
label="Parent Category"
:options="businessCategoriesToSelect"
:option-label="opt => Object(opt) === opt && 'title' in opt ? opt.title : null"
:option-value="opt => Object(opt) === opt && '#id' in opt ? opt['#id'] : null"
:display-value="Object(parentCategory) === parentCategory && 'title' in parentCategory ? parentCategory.title : null"
emit-value
map-options
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No Business Categories Found
</q-item-section>
</q-item>
</template>
<template v-slot:selected-item="scope">
{{ scope.opt.title }}
</template>
</q-select>

how to create dynamic input filters for columns in bootstrap-vue 2.0

I'm trying to create some dynamic filters in bootstrap-vue 2.0.0-rc.11 for the bootstrap-table columns
In my example I did this
<b-table class="io-store-list-table table-striped" show-empty hover stacked="md" :items="stores" :fields="storeFields" :current-page="currentPage" :per-page="perPage" :filter="filter" :sort-by.sync="sortBy" :sort-desc.sync="sortDesc" :sort-direction="sortDirection" #filtered="onFiltered" empty-filtered-text="{l s='There are no records matching your request' mod='ioweb_slocator'}">
<template slot="top-row" slot-scope="data">
<th v-for="field in fields">
<input v-if="field.filterable" type="text" #click.stop value="" />
</th>
</template>
<template v-for='field in formatted' :slot='field' slot-scope='row'>
<span v-html='row.value'></span>
</template>
</b-table>
<b-row>
<b-container>
<b-col xs="12" class="my-1 io-pagination">
<b-pagination :total-rows="totalRows" :per-page="perPage" v-model="currentPage" class="my-0"/>
</b-col>
</b-container>
</b-row>
</b-table>
Which renders a table like this
Now I'm attempting to filter the items based on what value is entered in each column. For example if I type mypartnername at the input box below Partner column, I would like to dynamically filter the items based on the row key called partner but I'm not sure how to approach this.
Based on the accepted answer I was able to create a structure that helped me like this.
Step 1:
Create a property filteredResults and set it equal to my unfiltered items property
let app = new Vue({
el: "#app",
data() {
return {
...
stores: stores,
groups: groups,
totalRows: stores.length,
filters: [],
loop: 0,
filteredResults: stores,
}
},
Step 2
Used filteredResults in the :items slot
Step 3
Create a single function to set the filters
methods: {
...
setFilter(property, value) {
console.log("Filtering");
this.filters[property] = {};
this.filters[property].value = value;
this.filteredResults = this.stores.filter(item => {
let keep = true;
// This is a basic equality filter. What I did in the actual code was to have an object with filter functions for each key. If a key was missing, it defaulted to straight equality.
this.fieldKeys.forEach(key => {
keep =
keep &&
(this.filters[key] === undefined || this.filters[key].value === undefined || this.filters[key].value === "" || item[key].match(this.filters[key].value));
});
return keep;
});
},
},
what about something like this? I dont know if i got your problem right.
<input v-if="field.filterable" #onchange="setFilter(field.property, $event.target.value)" type="text" #click.stop />
in the setFilter function you could do something like this:
setFilter(property, value) {
this.filters[property].value = value
}
get your results with a computed property
filteredResults(){
return users = this.users.filter((item) => {
for (var key in this.filters) {
if (item[key].value === undefined || item[key].value != filter[key])
return false;
}
return true;
}
}
I dont know if it works, couldnt test it. I am curious about the solution here.

Vue: Dropdown box in vue-select not showing value after selecting

I am populating a dropdown from a computed method that returns an array of store objects. Then in the vue-select, I am passing this in as options and having the option.address show in the dropdown. That is working as expected but when clicking a dropdown option, the box doesn't show the value -- it just remains blank.
computed: {
storeLocationsArray: function() {
let arr = [];
this.storeLocations.forEach((location,index) => {
arr.push({id: index, address: location.address})
})
return arr;
}
}
<v-select
v-model="selectedPickupLocation"
:options="storeLocationsArray"
>
<template class="single-option" slot="option" slot-scope="option">
{{option.address}}
</template>
</v-select>
You can use label to display address instead of slot
<v-select
v-model="selectedPickupLocation"
:options="storeLocationsArray"
label="address"
>
</v-select>

Unexpected side effect in computed property

I'm not sure why i'm getting an unexpected side effect in computer property error with the code below.
Error:
✘ https://google.com/#q=vue%2Fno-side-effects-in-computed-properties Unexpected side effect in "orderMyReposByStars" computed property
src/components/HelloWorld.vue:84:14
return this.myRepos.sort((a, b) => a.stargazers_count < b.stargazers_count)
html:
<div v-if="myRepos && myRepos.length > 0">
<h3>My Repos</h3>
<ul>
<li v-for="repo in orderMyReposByStars" v-bind:key="repo.id">
<div class="repo">
{{repo.name}}
<div class="pull-right">
<i class="fas fa-star"></i>
<span class="bold">{{repo.stargazers_count}}</span>
</div>
</div>
</li>
</ul>
</div>
js:
export default {
name: 'HelloWorld',
data () {
return {
myRepos: null, <-- THIS IS ULTIMATELY AN ARRAY OF OBJECTS
}
},
computed: {
orderMyReposByStars: function () {
return this.myRepos.sort((a, b) => a.stargazers_count < b.stargazers_count)
},
...
From what I can tell this looks correct according to the docs here https://v2.vuejs.org/v2/guide/list.html#Displaying-Filtered-Sorted-Results
.sort mutates the original array.
To avoid it, clone the array before sorting it.
.slice() is 1 of the simplest way to clone array. See https://stackoverflow.com/a/20547803/5599288
return this.myRepos.slice().sort((a, b) => a.stargazers_count < b.stargazers_count)
on a side note, null.sort() or null.slice() will throw error. Perhaps it would be better to set the initial value of myRepos to empty array [] instead of null
2021 easy & readable solution...
Just the use spread syntax:
computed: {
orderMyReposByStars: function () {
return [...this.myRepos].sort((a, b) => a.stargazers_count < b.stargazers_count)
},
}
My Solution is to add a filter before the sort.
Array.filter(() => true).sort((a, b) => a.menu_order - b.menu_order);

v-if doesn't recognize value from array of object

I'm working on a vueJS file and have a component :
<div class="panel-heading" v-on:click="displayValue(feature.id)">
{{ feature.nom }}
</div>
<div class="panel-body" v-if="getDisplay(feature.id)">
foo
</div>
my function displayValue(id) :
displayValue(id){
for(let i =0; i<this.product_site.displayFeatures.length;i++){
if (this.product_site.displayFeatures[i].idFeature === id){
this.product_site.displayFeatures[i].show = !this.product_site.displayFeatures[i].show
}
}
console.log(this.product_site.displayFeatures)
},
First I am not very happy with that. I trie to do a .find but it didn't work :
this.product_site.displayFeatures.find(function(a){
a.idFeature === id
}).show = true
But I had an error telling me can not read 'show' of undefined
and my function getDisplay(id)
getDisplay(id){
this.product_site.displayFeatures.forEach(function(a){
if(a.idFeature === id){
return a.show
}
})
}
same as before if I try with a find.
Anyway, I thought it would work with that, but when I do console.log(this.product_sites.displayFeatures) I have the array with the modified value but foo is not shown