Im having an array that looks something like this:
customers : [ {customer : 'foo', address : {postalCode : 6655, city : 'somewhere'}}, ..
]
I render a list something like this :
<template v-for="(cust, inx) in customers">
<div>{{ customers[inx].customer }}</div>
<div>{{customers[inx].address.postalCode }}|{{ customers[inx].address.city}}</div>
</template>
Now I have a function that gets the city when people enters a new postalcode it fetches a city and sets it with :
this.$set(self.customers[inx].address, 'city', 'NewCityName');
The thing is, I can confirm that the text is actually changed in the correct object, but it doesnt trigger a re-rendering.
Am I using the $set function in a wrong way in this case?
It could be that this.customers is not set correctly (is not marked as oservable) i.e. not declared in data like {customers:[]}, or any of its items are not set correctly. If you evaluate in devtools console, it must give out for this.customer and any of its items something like: {__ob__: Observer} and in expanded view must contain an item __ob__: Observer {value: {…}, dep: Dep, vmCount: 0}. These types of errors are most annoying in vue.
Object and array elements are observed only if they exist. Array methods like push, splice are observed too, so this.array[2] = obj will not work if array length < 2 but this.array.push(obj) works as expected. In other cases $set(...) is necessary to mark element as observable.
Related
So i have a b-form-select with a v-model i need to change dynamically my issue is when i change the v-model to another element of the list the :options are taken from the selected value doesn't change
Code example :
<b-form-select :options="ListA" v-model="Depart" value-field="Livreur" text-field="Livreur"></b-form-select>
data(){
Depart:'',
ListA:[],
}
my method is simply :
function(){
this.Depart = this.ListA[0]
}
the list is structured as such :
this.ListA.push({Livreur:"example",id:0})
as far as i know it should change the selected value of the b-form-select but instead nothing at all happens , any ideas ? thank you in advance
Your value-field should probably be id not Livreur, except if Livreur is a unique identifier as well.
Relevant part in the documentation: https://bootstrap-vue.org/docs/components/form-select#changing-the-option-field-names
this.Depart should also not be an object, but the value of the identifier you chose in the value-field property. In your case it should be:
if value-field is id:
this.Depart = this.ListA[0].id
if value-field is Livreur:
this.Depart = this.ListA[0].Livreur
I have the following Problem:
I'm using Ionic Vue and a VueX Store to save my data from an API.
Now I have set an array, which contains the IDs of entries, which shall be checked or unchecked.
Since I should not modify the API-Model class, I have saved the IDs of checked entries in a seperate Array in my VueX Store, which I update as needed.
Now I'm trying to make the checkboxes checked / unchecked depending on that array.
I tried it by adding v-model = "checkedVehicles.included(vehicle.vehicle_id)", but all I get is an Error:
'v-model' directives require the attribute value which is valid as LHS vue/valid-v-model
Heres the Part whit the checkboxes, hope that is all you need :)
<IonItem v-for="vehicle in vehicleList" v-bind:key="vehicle.vehicle_id">
<IonLabel>
<h2>{{ vehicle.manufacturer }} {{ vehicle.model }}</h2>
<p>{{ vehicle.display_name }}</p></IonLabel>
<IonCheckbox slot="end"
v-model="checkedVehicles.includes(vehicle.vehicle_id)"
#click="checkIfAllDeselected"
#update="this.updateCheckboxOnClick(vehicle.vehicle_id)"/>
</IonItem>
The checkedVehicles Arrays is intialized as String[].
Also tried to use a function, which returns true or false, depending on the checkedVehicles Array has the ID included or not, but that also gives the same error
The other functions, which add or remove entires to the correspondig arrays are working fine, already checked that. only the Checkboxes are not working as intended.
Has anyone a clue, what I'm doing wrong?
This is obvious because we can't evaluate a condition in v-model. We generally bind a variable to the v-model.
For eg:
Consider you have a attr called vehicle in data.
data() {
return {
Vehicle list: [{
checked: true,
manufacturer: '',
display_name: '',
vehicle_id: ''
},
{
checked: true,
manufacturer: '',
display_name: '',
vehicle_id: ''
},
]
}
then you can bind it as
<IonItem v-for="vehicle in vehicleList" v-bind:key="vehicle.vehicle_id">
<IonLabel>
<h2>{{ vehicle.manufacturer }} {{ vehicle.model }}</h2>
<p>{{ vehicle.display_name }}</p></IonLabel>
<IonCheckbox slot="end"
v-model="vehicle.checked"
#click="checkIfAllDeselected"
#update="this.updateCheckboxOnClick(vehicle.vehicle_id)"/>
</IonItem>
To conclude, variables that can hold value can only be used in v-model
I'm creating a list of (thumbnail) 2 images, and #click each image should be expanded to max-width, by adding said class ('max-w-full') to the classes. The class is added by setting the array entry with the same index nr. as the image (imgclicked[0], imgclicked[1]) in the list to 1.
data:() {
imgclicked=[0,0], //by default both are set to 'small'/not 'max-w-full'
},
the template part looks like this:
<template v-for="(image,index) in images>
<a #click="zoomImgClicked(index)">
<img :src="image.filename" :class={'max-w-full' : imgclicked[index]==1,'w-12' : imgclicked[index]==0}">
</a> // using this.imgclicked[index] gives me the error 'this.imgclicked[0] is undefined'
</template>
on click the method zoomImgClicked() ist launched:
zoomImgClicked: function(i){
if(this.imgclicked[i]==0){
this.imgclicked[i]=1
}else{
this.imgclicked[i]=0
}
},
But this is not working. If I open the vue console and change the values of imgclicked[0] manually from 0 to 1 it works (images ae being resized). Also I see the method doing it's work, when logging in the console, the values are changed from 0 to 1 and vice versa. But it's not reflected on the page #click.
Why is that?
Please read Change Detection Caveats in the Vue docs.
Vue cannot detect the following changes to an array:
When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
When you modify the length of the array, e.g. vm.items.length = newLength
You should use the $set method for this:
this.$set(this.imgclicked, i, 1)
try with array syntax:
<img
:src="image.filename"
:class="[
{
'max-w-full': imgclicked[index]==1,
'w-12': imgclicked[index]==0
},
'static class if need'
]"
>
Currently I display a list of hotels for each city in a Vue.js / Buefy form using:
<option
:value="h['#attributes'].Name"
v-for="h in cities[form.cities[i].index].Hotels.Hotel"
:key="cities[form.cities[i].index].Hotels.Hotel.Name"
v-if="isArray(form.cities[i].index)"
v-text="h['#attributes'].Name"></option>
What should I add to sort them alphabetically? I'm at loss, as I don't know Vue / Buefy so well and I'm modifying a code somebody else wrote.
Thanks!
It is important to understand what your code is doing so that you know where you need to make changes.
Your loop v-for is iterating over your array cities[form.cities[i].index].Hotels.Hotel (the naming seems odd to me).
Within this array, there is a key #attributes which holds an object with a key Name, which is probably what you want to use for sorting.
Normally I would go with computed properties for these things but since you have the array based on a parameter (form.cities[i].index) I am not sure that would work so easily. So instead you can use a method to get a sorted version of your array. In your Vue instance, add the following to the "methods" property:
methods: {
sortedHotels: function(hotels) {
tmp = this.hotels.slice(0);
tmp.sort(function(a,b) {
return (a['#attributes'].Name > b['#attributes'].Name) ? 1 : ((b['#attributes'].Name> a['#attributes'].Name) ? -1 : 0);
});
return tmp;
},
},
Then, instead of looping through the normal array, you loop through the result of the function call of that array:
<option
:value="h['#attributes'].Name"
v-for="h in sortedHotels(cities[form.cities[i].index].Hotels.Hotel)"
:key="cities[form.cities[i].index].Hotels.Hotel.Name"
v-if="isArray(form.cities[i].index)"
v-text="h['#attributes'].Name"></option>
I'm trying to get object items from inside a parent object using a v-for inside another v-for in Vue.js.
Data structure:
flights: [
{
"airline": "BA",
"airport": "EBJ",
"status": {
"_code": "A",
"_time": "2018-03-02T14:19:00Z"
}
},
etc....
]
<div v-for="flight in flights">
<p>{{flight.airline}}</p>
<p>{{flight.airport}}</p>
<div v-for="st in flight.status">
<p>{{st._code}}</p> // should return 'A'
<p>{{st._time}}</p> // should return '2018-03-02T14:19:00Z'
</div>
</div>
However, neither st._code or st._time return anything. st returns both values ("A" and "2018-03-02T14:19:00Z").
Any idea on how to return the single values inside the status object?
It is possible to use v-for on an object, as you're trying to do with status, but the syntax is slightly different; in cases where iterating over an object is useful you'll generally want to include the key as well as the value:
<div v-for="(val, key) in flight.status">
<p>{{key}}: {{val}}</p>
</div>
would output
<p>_code: A</p>
<p>_time: 2018-03-02T14:19:00Z</p>
In your case you already know the specific keys you want, so it would be easier to not use v-for and instead just use e.g {{flight.status._code}}.
Unless there can be more than one "status" per flight, there's no good reason to wrap status in an array. This will work with your existing data structure:
<div v-for="flight in flights">
<p>{{flight.airline}}</p>
<p>{{flight.airport}}</p>
<p>{{flight.status._code}}</p>
<p>{{flight.status._time}}</p>
</div>
The reason you are not seeing the expected output is because, of this line:
<div v-for="st in flight.status">
That means you are expecting vue to iterated throught this:
"status": {
"_code": "A",
"_time": "2018-03-02T14:19:00Z"
}
and the above is an object, not an array ... so unless status is an array, it won't work.
If you expect your code to work, try changing your array to this:
flights: [
{
"airline": "BA",
"airport": "EBJ",
status: [{
"_code": "A",
"_time" : "2018-03-02T14:19:00Z"
}]
}
]
working demo:
https://jsfiddle.net/943bx5px/82/