in_array() in Vue .js [duplicate] - vue.js

This question already has answers here:
How do I check if an array includes a value in JavaScript?
(60 answers)
Closed 7 months ago.
I get this error : "TypeError: _vm.in_array is not a function" when I use in_array() function.
Is there any similar function like in_array() in Vue.js?
I want to do something like this and the result should display abc.
<template v-if="in_array(number,list)">
<h3> abc </h3>
</template>
<script>
data() {
return {
list: [1,2,3],
}
},
</script>

in_array is not a function in JavaScript, you can use includes in a computed property to make this work tho.
Pseudocode:
<template v-if="in_array">
<h3> abc </h3>
</template>
<script>
data() {
return {
number: 1,
list: [1,2,3],
}
},
computed: {
in_array() {
return this.list.includes(this.number)
}
}
</script>

Related

Vue + Pug - Dynamic attribute names [duplicate]

This question already has an answer here:
How to reference data from vue,js pug template?
(1 answer)
Closed last year.
How to correctly add dynamic attribute names in a Vue template using Pug? I'm using the following template:
<template lang="pug">
button(id=`button__${buttontype}`)
slot(name="text")
</template>
<script>
export default {
name: "Button",
data() {
return {
buttontype: "primary"
},
},
mounted() {
console.log(this.test); // This shows the value as 'primary'
},
};
</script>
The HTML element being generated is <button id="button__undefined"></button>
The value of buttontype is coming as undefined in the id attribute for some reason.
Try using v-bind:
<template lang="pug">
button(v-bind:id=`button__${buttontype}`)
slot(name="text")
</template>
The following template worked:
<template lang="pug">
button(:class="[`button__${test}`]")
slot(name="text")
</template>

Vue: Updating a data property triggers re-evaluation of entire data?

I've been working on Vue project for almost a year, and I've just observed unexpected behavior below for the first time today...
Here is a link to code sandbox:
https://codesandbox.io/s/2bnem?file=/src/App.vue
And a code snippet from above link:
<template>
<div>
<div>{{a}}</div>
<div>{{translator(b)}}</div>
<input v-model="a" />
</div>
</template>
<script>
export default {
data() {
return {
a: 'a',
b: 'b',
}
},
computed: {
translator: function() {
return function(value) {
console.log(`translated...: ${value}`)
return value
}
}
}
}
</script>
Now every time I hit the key on input, the translator is triggered.
Is this a correct behavior?
If so, what is the cause of this problem or a background reasoning of this behavior?
Note that my vue version is 2.6.14(latest).
Your original issue is that you were attempting to use a method to render parts of your template. Methods used like this will execute for every update cycle, regardless of what changed.
The better solution is to use a computed property. Here's a somewhat dynamic example that wraps each of your data properties with a computed translator_x property
<template>
<div>
<div>{{ a }}</div>
<div>{{ translator_b }}</div>
<input v-model="a" />
</div>
</template>
<script>
const defaultData = {
a: "a",
b: "b"
}
export default {
data: () => ({ ...defaultData }),
computed: Object.fromEntries(Object.keys(defaultData).map(k => [
`translator_${k}`,
vm => {
console.log("translated...", k)
return vm[k]
}
]))
};
</script>
Each translator_x property will only be evaluated if the underlying data property is changed.

Vue JS Sort Date with components using Computed Property

I tried to sort the date using computed properties but it didnt work, if i using at methods and remove the slice, then it will sort as expected. I've tried to split the date also but still not working. I am not sure what caused the problem.
Kindly find my code as below.
App
<template>
<div>
<h2>Ingredients</h2>
<ul>
<li></li>
</ul>
<ingredients-list v-for="(ingredient,index) in ingredients"
:key="index"
:index='index'
:foodName="ingredient.food"
:foodExpiry="ingredient.expiryDate">
</ingredients-list>
</div>
</template>
<script>
export default {
data(){
return{
ingredients:[
{
food:'carrot',
expiryDate:'2020-12-12'
},
{
food:'papaya',
expiryDate:'2018-1-15'
},
{
food:'orange',
expiryDate:'2021-10-13'
},
{
food:'meat',
expiryDate:'2019-4-23'
}]
}
},
computed: {
sortedItems() {
return this.ingredients.slice().sort( ( a, b) => {
return new Date(a.expiryDate)- new Date(b.expiryDate);
});
}
}
}
</script>
components
<template>
<div>
<h2>{{index}}</h2>
<h2>Food:{{foodName}}</h2>
<h2>Expiry:{{foodExpiry}}</h2>
</div>
</template>
<script>
export default {
props:['foodName','foodExpiry'],
}
</script>
Like #Anatoly said
Computed props are never calculated if they are not used at all.
What you should be doing to solve the problem is :
Using slice method instead of splice since it mutates the original array:
sortedItems() {
return this.ingredients.slice()
.sort((a, b) => new Date(a.expiryDate)- new Date(b.expiryDate));
}
Loop through the computed property and not the original array:
<ingredients-list v-for="(ingredient,index) in sortedItems"
:key="index"
:index='index'
:foodName="ingredient.food"
:foodExpiry="ingredient.expiryDate">
</ingredients-list>
It seems you confused splice with slice. You need slice to get a copy of an array and to sort this copy:
sortedItems() {
return this.ingredients.slice().sort( ( a, b) => {
return new Date(a.expiryDate)- new Date(b.expiryDate);
});
}

Vue how to copy array locally for editing? Why does it work for strings and not arrays? [duplicate]

This question already has an answer here:
Creating local copy of passed props in child component in vue.js?
(1 answer)
Closed 2 years ago.
I made a demo to test an issue with my larger project, I am making a settings menu where I want to copy some props, edit them and save them. To do this I need to copy the props for local use. For some reason, the array wont copy properly and a $set will change the array for the parent function. See below.
Child Code below
<script>
export default {
name: "HelloWorld",
props: {
data: Object,
},
data: function(){
return{
localData : {}
}
},
mounted(){
this.localData = Object.assign({},this.data)
},
methods: {
changeData() {
console.log("changing parent data");
console.log(this.localData)
this.localData.name = "new name"
this.$set(this.localData.array, 0, 1000); //change first indes to 1000
},
},
};
</script>
<template>
<div class="child">
Child {{localData}}
<br />
<button #click="changeData()">Change Data</button>
</div>
</template>
Parent Code
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<p>Parent {{data}}</p>
<Child :data="data"/>
</div>
</template>
<script>
import Child from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
Child
},
data: function(){
return {
data: {'name':'hello world','array':[1,2,3,4]}
}
}
}
</script>
As the image shows, after the button is pressed, the name value remains local to the child copy of the object, however the array is not. How can the array be changed locally without the parent changing as well. Thanks
Try out to use the spread operator:
this.localData = {...this.data}

Vue v-once equivalent

Is there a way to tell Vue to call a method only once when used as an expression?
Here's my code:
<div v-for="i in a.b.c.items">
<div :id="foo(i.value)"></div>
</div>
The way it is now, the foo() method will be executed any time anything on the model changes, not only items. Is there something in Vue that I can tell to evaluate this only once?
like this: <div :id.only-once="foo(i.value)"
Unfortunately that's only possible for certain events, e.g. in this question here. What you may want to consider instead is a computed property where you compute all of these values and return the array. This resulting array will be cached by Vue and will not be reevaluated until your items array is modified (and modified in such a way that Vue will detect the change).
An example:
Vue Setup
<script>
new Vue({
el: '. . .',
data: {
a: {b: {c: {items: [. . .]}}}
},
methods: {
foo: function(val) {
. . .
}
},
computed: {
itemsAfterFoo: function() {
var this_vue_instance = this;
var computed_items = [];
this_vue_instance.items.forEach(function(item) {
computed_items.push(this_vue_instance.foo(item.value));
});
return computed_items;
}
}
});
</script>
Template
<div v-for="(i, index) in a.b.c.items">
<div :id="itemsAfterFoo[index]"></div>
</div>
Or something to that effect.
More information on computed properties here: https://v2.vuejs.org/v2/guide/computed.html