Vue.js this is undefined inside computed property - javascript

I have following input tag with model selectedProp:
<input type="text" v-model="selectedProp" />
and I want to iterate through items like this:
<div v-for="item of filteredItems">{{item.prop}}</div>
Here's the script for the component:
export default {
name: 'App',
data() {
return {
items: [],
selectedProp: "",
projects: [],
errors: []
}
},
created() {
axios.get(`${URL}`)
.then(response => {
// JSON responses are automatically parsed.
this.items = response.data;
})
.catch(e => {
this.errors.push(e)
});
},
computed: {
filteredItems() {
if(this.selectedProp) {
console.log(this.selectedProp);
return this.items.filter(function (item) {
return item.prop == this.selectedProp;
});
}
return this.items;
}
},
}
Error
this is undefined inside computed property

In this case you could use arrow function which has access to this object
return this.items.filter( (item)=> {
return item.prop == this.selectedProp;
})

Related

Vue metaInfo undefined in watch

I am inserting vue-meta logic inside the current code and there seems to be a problem that metaInfo is not available yet when watch is triggered.
export default {
metaInfo () {
return {
title: this.title,
meta: [],
}
},
watch: {
article() {
if (this.article) {
this.generatedHtml = this.applySnippets();
}
},
},
computed: {
article() {
return this.$store.getters.CONTENT;
},
title() {
if (this.article !== null) {
return this.article.info.caption;
}
return '';
},
}
created() {
this.$store.commit('CLEAR_CONTENT');
this.$store.dispatch('FETCH_CONTENT', { slug: this.slug, component: this });
},
methods: {
applySnippets() {
if (!this.article.snippets || this.article.snippets.length === 0) {
return this.article.data.content;
}
this.article.snippets.forEach(snippet => {
if (snippet.type === 'meta')
this.metaInfo.meta.push(snippet.object);
});
},
It fails that this.metaInfo is undefined during this Vue lifecycle phase. What to do?
To access the metaInfo result in the Options API, use this.$metaInfo (note the $ prefix):
if (snippet.type === 'meta')
this.$metaInfo.meta.push(snippet.object);
👆
demo

I cannot implement a filter to my array in vue.js

I've been looking for quite a while but being a novice I can't find an answer.
I would like to filter my array with the id of a property I think is the wrong syntax.
Thanks for your help
components
export default {
props: ["user", "recette"],
data() {
return { email: this.$route.params.email };
},
components: {},
methods: {},
computed: {
filteredItems: function () {
return this.recette.filter((recettes) => {
return recettes.cat_recetteId === 1;
});
},
},
};
VIEW
<template>
<div>
<myrecette :recette="recette"/>
<myfooter />
</div>
</template>
<script>
import myrecette from "../components/recette";
import myfooter from "../components/myfooter";
export default {
name: "",
data() {
return {
recette: "",
user: "",
};
},
components: {
myrecette,
myfooter,
},
created: function() {
this.axios.get("http://localhost:3000/recette/all_recette/").then((res) => {
(this.recette = res.data.recette),
this.axios
.get(
"http://localhost:3000/user/rec_user/" + this.$route.params.email
)
.then((res) => {
this.user = res.data.user;
});
});
},
};
</script>
<style scoped></style>
NODE
router.get("/all_recette", (req, res) => {
db.recette
.findAll({
include: { all: true },
})
.then((recette) => {
if (recette) {
res.status(200).json({
recette: recette,
});
} else {
res.json("il n'y a pas de recettes");
}
})
.catch(err => {
res.json(err);
});
});
Here is my complete code as well as my node route.
My error return is
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: this.recette.filter is not a function"
The filter works by keeping items which return true, so if you want all items having a cat_recetteId of 1, you would change it to:
computed: {
filteredItems: function() {
if (!this.recette) return [];
return this.recette.filter((recettes) => {
return recettes.cat_recetteId === 1;
});
},
},
It's also good practice to use an arrow function in most cases inside of a computed.
Your filter callback function should return true or false. You're 1) not returning anything and 2) assigning a value (=) instead of doing a comparison (==/===).
computed: {
filteredItems: function() {
return this.recette.filter(function(recettes) {
return recettes.cat_recetteId === 1;
});
},
},

How to initialize data correctly in vue js?

It takes the initTableData and initTableFiltered after onChangeDistrict which i hope to not take it now, instead to take only the initTableFiltered
data () {
return {
data: []
}
},
created () {
this.initTableData()
},
methods() {
initTableData () {
db.collection('example').orderBy('owner_name', 'asc').get().then(res => {
res.forEach((doc) => {
this.data.push({
id: doc.id,
})
})
})
},
initTableFiltered () {
db.collection('filter').orderBy('name', 'asc').get().then(res => {
res.forEach((doc) => {
this.data.push({
id: doc.id,
})
})
}
onChangeDistrict () {
this.initTablefiltered()
}
}
So how to initialize the initTablefiltered freshly on onChangeDistrict?
Did you create data variable? This isn't in the code?
Ex:
export default {
data() {
return {
data: []
}
},
...
Without instantiate your data, this is not reactive...

Filtering a table by using vue multiselect

I'm trying to filter the results of a table by using vue-multiselect. I can see the selected values in the VUE dev tools as a part of multiselect component. How do I use these values to be used in filter() function to get the filtered table results.
Below you can see my JS script implementation and Template multiselect implementation as well.
JS Script
export default {
data: () => ({
policies: [],
selectedValues: [],
options: [],
}),
methods: {
filterByStatus: function({ label, value }) {
return this.policies.filter(data => {
let status= data.status.toLowerCase().match(this.selectedValues.toLowerCase());
},
Template
<multiselect
v-model="selectedValues"
:options="options"
:multiple="true"
label="label"
track-by="label"
placeholder="Filter by status"
#select="filterByStatus"
></multiselect>
Your select component is using the prop :multiple="true", this means the bound value selectedValues, with v-model, will return an array of policy objects.
Instead of using a filterByStatus function in the methods component options, create two computed properties.
One that computes an array of the selected policies statuses and another one that computes the filtered array of policies you want to display.
Script:
computed: {
selectedStatuses() {
const statuses = []
for (const { status } of this.selectedValues) {
statuses.push(status.toLowerCase())
}
return statuses
},
filteredPolicies() {
if (this.selectedStatuses.length === 0) {
return this.policies
}
const policies = []
for (const policy of this.policies) {
if (this.selectedStatuses.includes(policy.status.toLowerCase())) {
policies.push(policy)
}
}
return policies
}
}
Template:
<multiselect
v-model="selectedValues"
:options="options"
:multiple="true"
label="label"
track-by="label"
placeholder="Filter by status"
></multiselect>
Example:
Vue.config.productionTip = Vue.config.devtools = false
new Vue({
name: 'App',
components: {
Multiselect: window.VueMultiselect.default
},
data() {
return {
policies: [{
label: 'Policy A',
status: 'enabled'
}, {
label: 'Policy B',
status: 'disabled'
}, {
label: 'Policy C',
status: 'Deprecated'
}],
selectedValues: [],
options: [{
label: 'Enabled',
status: 'enabled'
}, {
label: 'Disabled',
status: 'DISABLED'
}, {
label: 'Deprecated',
status: 'DePrEcAtEd'
}]
}
},
computed: {
selectedStatuses() {
const statuses = []
for (const {
status
} of this.selectedValues) {
statuses.push(status.toLowerCase())
}
return statuses
},
filteredPolicies() {
if (this.selectedStatuses.length === 0) {
return this.policies
}
const policies = []
for (const policy of this.policies) {
if (this.selectedStatuses.includes(policy.status.toLowerCase())) {
policies.push(policy)
}
}
return policies
}
},
}).$mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect#2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
<div id="app">
<multiselect v-model="selectedValues" :options="options" :multiple="true" label="label" track-by="label" placeholder="Filter by status"></multiselect>
<pre>Policies: {{ filteredPolicies}}</pre>
</div>
It is better to keep the filter function inside computed.
computed:{
filterByStatus: function ({label, value}) {
return this.policies.filter((data) => {
return data.status && data.status.toLowerCase().includes(this.selectedValues.toLowerCase())
});
}
}
Using the filterByStatus in the template section will render the result in real time.
<div>{{filterByStatus}}</div>
you can use watch on selectedValues when any change or selection :
watch:{
selectedValues: function(value){
this.policies.filter(data => {
let status= data.status.toLowerCase().match(this.selectedValues.toLowerCase());
}
}
This how I did in one of my vue3 projects, where I had multiple dropdowns with multi-items can be selected to filter and with a text input box:
const filterByInput = (item: string) =>
item.toLowerCase().includes(state.searchInput.toLowerCase());
const filteredItems = computed(() => {
let fItems = JSON.parse(JSON.stringify(props.items));
if (state.searchInput) {
fItems = fItems.filter((item) => filterByInput(item.title));
}
if (state.filterByState.length) {
fItems = fItems.filter((item) => state.filterByState.includes(item.state));
}
if (state.filterByType.length) {
fItems = fItems.filter((item) => state.filterByType.includes(item.typeId));
}
if (state.filterByPublishing !== null) {
fItems = fItems.filter((item) => item.published === state.filterByPublishing);
}
return fItems;
// NOTE: other options that you can try (should be placed above `return`)
// const filterMultiSelect = (fItems, selectedItems, key) => {
// // OPT-1: foreach
// const arr = [];
// fItems.forEach((item) => {
// if (selectedItems.includes(item[key])) {
// arr.push(item);
// }
// });
// return arr;
// // OPT-2: filter
// return fItems.filter((item) => selectedItems.includes(item[key]));
// };
// if (state.filterByState.length) {
// fItems = filterMultiSelect(fItems, state.filterByType, 'typeId');
// }
});
You can find full code in this gist

compiler returns: "'value' is defined but never used" when I used it

I want to get in the api with function value and return USD instead of making a lot of functions without value I'm trying this code but compiler returns 'value' is defined but never used
any ideas?
data(){
return {
posts: [],
}
},
methods: {
changeCurrency: function (value) {
axios.get('http://data.fixer.io/api/latest?access_key=509c9d50c1e92a712be9c8f1f964cf67')
.then(response => {
this.currency = response.data.rates.value
})
},
}
<button #click="changeCurrency(USD)">
USD
</button>
data(){
return {
posts: [],
}
},
methods: {
changeCurrency: function () { // removed unused variable "value" here
axios.get('http://data.fixer.io/api/latest?access_key=xxxxxx')
.then(response => {
this.currency = response.data.rates.value
})
},
}
The parameter value is passed to the changeCurrency function but it is never used in the function itself. Your Linter complains about it due to no-unused-vars rule.
data(){
return {
posts: [],
}
},
methods: {
changeCurrency: function () { // <-- removed `value` from here. Should pass the linter
axios.get('http://data.fixer.io/api/latest?access_key=xxxxxx')
.then(response => {
this.currency = response.data.rates.value
})
},
}

Categories

Resources