Vuejs reactive binding of strings in a array - vue.js

I have a plain array of strings in my data and I would like to enable their editing/adding with
<ul>
<li v-for="(string, index) in strings" :key="index">
<input v-model="string">
</li>
</ul>
the problem is that the strings in the array are not changed when the user types in the input.
Here is a Jsfiddle https://jsfiddle.net/franta/74ybd0g5/10/
I would like the "Strings" part to work like the "Things".
Thanks

Try this: v-model="strings[index]"
By doing this you are passing by reference and not by value. Meaning, instead of having two separate instances between strings and your v-model="string" they both share the same instance instead.

Related

vuejs expression is not working correctly

what is wrong with my expressions? I am making a rest api call, which works fine. Data loads and gets written to console. I am simply trying to get that data on screen. I can but its not correct. It either shows all of the data. I am only trying to get the first item in the array. items.Name does not work, but it does if I do a v-for="item in items". Regardless it loads everything. When I add a [0] to get the first element, it simply removes all the text except the first letter of the object in the array.What do I need to do?
<p>{{items.Name}}</p>
Please, read the docs about list rendering
https://v2.vuejs.org/v2/guide/list.html
If you have an items array of objects, then you can loop over it in your HTML by using v-for, or directly access each entry by specifying the index in the expression: {{ items[0].Name }}
<ul>
<li v-for="item in items" :key="item.ID">{{ item.name }}</li>
</ul>
Notice you're using item, not items, inside the <li> tag, because you instructed v-for to assign the cursor to that variable.

aurelia/html repeat.for - redundant elements

I have the following html (view):
<li>
<b>Institute:</b> Length: ${institutes.length}
<ul>
<li repeat.for="el of institutes">
${el.institute}: ${el.terminalCount}
</li>
</ul>
</li>
I see the following in the browser:
As seen, the array institutes has 2 elements, but in list I see 4 more rows - with empty values.
What is it? How I can fix it?
Thanks in advance.
You definitly have something else on that array apart from the elements. Otherwise it would be just two LI tags.
If you look # the source
there are number of repeater strategies in aurelia templating. Depending on the type of the object you want to iterate over.
If you are actively developing something with aurelia, I suggest you join the official aurelia discourse
And the gitter channel

Aurelia not outputting attribute with string interpolation in repeat

Is there any reason why a repeat.for binding would remove attributes from elements inside the repeater?
<div repeat.for="i of model.someArray.length">
<label>Some Array - Index ${i + 1}</label>
<input value.bind="model.someArray[i]" some-custom-attribute="someArray[${i}]"/>
</div>
and that some-custom-attribute is not being output within the repeat, but if I were to remove the string interpolation within there then it outputs fine.
== Edit ==
I have put it in a comment but just to make sure everyone is on the same page, ideally this is the output I expect:
<input value.bind="model.someArray[i]" some-custom-attribute="someArray[0]"/>
The some-custom-attribute is not an aurelia attribute, its pure HTML that a 3rd party JS library uses, so the goal here is to get the textual value of the index into the textual attribute value.
model.someArray.length is a number, not an array. You need to iterate over the array. If you do need the current index, the repeater provides the $index property for you to use.
Your code should look like this:
<div repeat.for="item of model.someArray">
<label>Some Array - Index ${$index + 1}</label>
<input value.bind="item" some-custom-attribute.bind="item"/>
</div>
To answer your original question, doing some-custom-attribute="model.someArray[${i}]" makes Aurelia think you are trying to pass a string value to the custom attribute. You can see that in the following gist: https://gist.run/?id=eed8ac8623ff4749aa5bb93c82a7b1fb I've created a custom element that just pushes whatever value it is given in to an element on the page. Note!!! Don't ever do what I'm doing here! I just did this this way so you wouldn't have to open the js console. To actually get a value passed in, you would need to use some-custom-attribute.bind="item" or (to do things how you are doing things, some-custom-attribute.bind="someArray[i]"

Naming the model and initliaze it dynamically in Vue.js

I am aware in Vue, every reactive data properties need to be declared in the Vue instance.
I have a situation where I need pull sets of data from the server, say tickets, and I need to have a model associated to each of these data when using v-for
Is there any way I can name the v-model using the ticket variable properties, ie the id. Is this possible?
v-model="{{ ticket.id }}"
If it is possible, how I declare the reactive data properties in vue instance dynamically?
Something like this:
<div id="example-1">
<div v-for="ticket in tickets">
<p> {{ticket.name }} </p>
<input type="number" v-model="{{ ticket.id }}" min="0" placeholder="0">
</div>
</div>
Answer of second question
You can use vm.$set for your case. This can add new reactive properties dynamically.
Set a property on an object. If the object is reactive, ensure the property is created as a reactive property and trigger view updates.
So once you receive response from server, you can apply vm.$set on the received object.
Answer of first question
Yes, you can name the v-model using the ticket variable properties using v-model, however syntax you are using is little wrong, it should be:
v-model="ticket.id"
Assuming you populate the tickets array in your Vue components' data object once received from the server, you can then iterate the array of tickets as you laid out in your example.
You can then tie the input model to the ticket object property directly:
<input type="number" v-model="ticket.id" min="0" placeholder="0">

Error if don't check if {{object.field}} exists

I have a question about checking if some field in object exists.
I want to print all categories which user has so I'm doing something like this:
<ul *ngIf="user.categories.length > 0" *ngFor="#category of user.categories">
<li>
{{category.name}}
</li>
</ul>
The reason? All the data are PROPERLY printed, but I'm getting an error in web console like this:
Cannot read property 'name' of null
But when I do something like:
<ul *ngIf="user.categories.length > 0" *ngFor="#category of user.categories">
<li *ngIf="category">
{{category.name}}
</li>
</ul>
Then all is okay.
Am I doing something wrong or maybe I have to check this every time? Have you ever had a problem like this one?
basic usage
Use the safe-navigation operator
{{category?.name}}
then name is only read when category is not null.
array
This only works for the . (dereference) operator.
For an array you can use
{{records && records[0]}}
See also Angular 2 - Cannot read property '0' of undefined error with context ERROR CONTEXT: [object Object]
async pipe
With async pipe it can be used like
{{(chapters | async)?.length
ngModel
With ngModel currently it needs to be split into
[ngModel]="details?.firstname" (ngModelChange)="details.firstname = $event"
See also Data is not appending to template in angular2
*ngIf
An alternative is always to wrap the part of the view with *ngIf="data" to prevent the part being rendered at all before the data is available to prevent the dereference error.