Why do not render checkboxes with checked attribute true vuejs - javascript

I am working an edit form, it happens that I have several options to choose, these options are obtained by ajax with axios and I assign them to the variable permisos of the component that later renders through a v-for, the checked elements I have them in a array selected that is assigned to the vue-model as follows
<div class="row">
<div v-for="permiso in permisos" class="col-md-5 col-12 col-sm-5" >
<input type="checkbox" :value="permiso.id"
class="form-control" :id=permiso.id
v-model="selected" :checked=selected.filter(e => e.id === permiso.id).length > 0 > {{ permiso.name}}
</div>
</div>
later I make another ajax call to know what options I had before editing the item to know what options or checkbox I will assign the checked attribute, this is where I have problems do not check correctly.
axios.get('api/allpermisos')
.then(response =>{
this.permisos = response.data; //dataok
})
if(this.action===2){
axios.get('api/allpermisos/'+ this.dataobject.id)
.then(response =>{
this.selected = response.data;//data ok
})
}
How can I do so that when I get the ajax call from the options already selected, the attribute checked is assigned automatically and those that are not, are not assigned. try with includes but I do not have the desired result?
The code works correctly if I remove the v-model. Why is this happening?
<input type="checkbox" :value="permiso.id" class="form-control"
:id=permiso.id :checked=selected.filter(e => e.id === permiso.id).length > 0 > {{ permiso.name}}

You don't need both v-model and :checked. v-model is a two way binding.
https://jsfiddle.net/bbsimonbb/eywraw8t/15613/
<div v-for="permiso in permisos" class="col-md-5 col-12 col-sm-5" >
<input type="checkbox" :value="permiso.id"
class="form-control" :id=permiso.id
v-model="selected"> {{ permiso.name}}
</div>
Consider creating a component for your input. Form inputs inside a v-for rapidly gets complicated.

You need to keep their ids in "selected" array, you are probably keeping whole objects which didn't work from what I checked.
HTML:
<div id="app">
<div class="row">
<div v-for="permiso in permisos" class="col-md-5 col-12 col-sm-5" >
<input type="checkbox" :value="permiso.id"
class="form-control" :id=permiso.id
v-model="selected" :checked=selected.includes(permiso.id)> {{ permiso.name}}
</div>
</div>
</div>
Vue:
new Vue({
el: '#app',
data() {
return {
selected: [2, 4],
permisos: [{id: 1, name: "test1"}, {id: 2, name: "test2"}, {id: 3, name: "test3"}, {id: 4, name: "test4"}]
}
}
})
https://jsfiddle.net/eywraw8t/15555/
This works.
If you are getting object array as response, you could do this:
this.selected = response.data.map(obj => obj.id);

Related

How to get all checkboxes values in Angular (10+)?

I retrieve from the database what options should I show for all companies (only for showing purposes), this is my model:
export class OpcionesModel {
name: string;
isActive: boolean;
id?: string;
}
Then, I show all the options that are available (active):
<div class="row" *ngFor="let option of optionsArray; let i=index">
<div class="col-4">
<h5>{{option.name | titlecase}}</h5>
</div>
<div class="col">
<input type="checkbox">
</div>
</div>
What I want to do is to get all option's names and if its checkbox is checked or not and store that in an array, e.g:
[{'option 1', true}, {'option 2'}, false}, {'option 3', false}...].
EDIT: I've created an array: checkes: boolean[] =[];
if I do this <input type="checkbox" [(ngModel)]="checkes[i]">, I can get the checkboxes value but I need the option name too.
Thanks !!
<label>
<input type="checkbox" name="isActive" [(ngModel)]="option.isActive">
{{ option.name }}
</label>
taken from here: https://scotch.io/tutorials/how-to-deal-with-different-form-controls-in-angular-2
In your ts file, Your optionsArray array will be binded and the checked values will be updated when it changes
If you want to map it to an array with a different structure you can use the map method:
this.optionsArray.map(oa=> {return { myOptionName:oa.name, active:oa.isActive} })

how to take dynamic v-model in vuejs in v-for loop

I am using v-form. and I am trying to take some input field in v-for loop dynamically. here is my code
<div class="row attribute-fields">
<div class="col-md-4 col-sm-12 col-lg-4" v-for="(singleAttribute,index) in attributes"
:key="index">
<div class="form-group">
<label for="attribute_name">{{ singleAttribute.attribute_name }}</label>
<input type="text" class="form-control" id="attribute_name"
:placeholder="singleAttribute.placeholder" v-model="form.attribute[index]">
</div>
</div>
</div>
and this attribute is comming after on Change a selectLIst ok thats give me the response. but i got a error in v-model. like this
and in data property in initialized my variable like this
form: new Form({
id: '',
category_id: '',
subcategory_id: '',
child_category_id:
attribute: [],
})
now i want to save all inputs value in attribute varibale using their index number.like
form.attribute[1] = 'value';
PLease help me to solve this problem

Child of data object not being evaluated until logged. Vue.js

I am writing a component (form) that acts as a container for form fields that are passed from the parent component.
I pass the form fields to the child as a prop:
formFields: [
{ name: 'email', type: 'email' },
{
name: 'sub_group',
type: 'group',
contents: [
{ name: 'sub_field_01', type: 'text' },
{ name: 'sub_field_02', type: 'text' },
]
}
]
That is all displayed fine and works well in my child component.
I used a computed property to build up data to post to a route to update the resource. I group the sub_group so that when I am posting, the controller understands that the sub_group is an array.
However, the sub_group array is always empty until I console log it, so it only evaluates when logged. The top level (email in this case) always shows up.
I have tried getting rid of the computed property and use a method to build up the object to post but I have the same issue. I really have no idea what is happening. How can 'force' the computed property to evaluate?
EDIT Adding form example
Code that renders the form:
<div v-for="field in formFields">
<!-- Individual Field -->
<div v-if="field.type !== 'group'">
<label v-if="field.label">{{ field.label }}</label>
<input :type="field.type" :name="field.name" v-model="field.value">
</div>
<!-- Group -->
<div v-else>
<div v-for="child in field.group">
<label v-if="child.label">{{ child.label }}</label>
<input :type="child.type" :name="child.name" v-model="child.value">
</div>
</div>
</div>
Computed property for post:
<div v-for="field in formFields">
<!-- Individual Field -->
<div v-if="field.type !== 'group'">
<label v-if="field.label">{{ field.label }}</label>
<input :type="field.type" :name="field.name" v-model="field.value">
</div>
<!-- Group -->
<div v-else>
<div v-for="child in field.group">
<label v-if="child.label">{{ child.label }}</label>
<input :type="child.type" :name="child.name" v-model="child.value">
</div>
</div>
</div>
I realise this needs refactoring but I can't actually get it working like this. I have tried adding cache:false and a getter to the computed property but that didn't work.

Create a two-way binding in vue.js between an array and multiple text inputs

My data is stored in an array. For each array item, there should be a text input in the form. When the user types into one of the text inputs, the array should be updated with the new values.
<div class="form-group" v-for="synonym in row.synonyms">
<input type="text" class="form-control" v-model="synonym" />
</div>
Here's a fiddle: https://jsfiddle.net/eywraw8t/122210/
The idea is when you type into one of the textboxes, the array value (shown below in that fiddle) should also update, but it doesn't.
Upon inspecting the console, you would find the following error:
You are binding v-model directly to a v-for
iteration alias. This will not be able to modify the v-for source
array because writing to the alias is like modifying a function local
variable. Consider using an array of objects and use v-model on an
object property instead.
Meaning, we need to give v-model access to a direct reference to the synonym and its index:
new Vue({
el: "#app",
data: {
row: {
synonyms: [
"abc",
"def",
"ghj",
]
}
},
methods: {
}
})
body {
font-family: 'Exo 2', sans-serif;
}
#app {
margin: auto;
}
<div id="app">
<h2>Items</h2>
<div class="form-group" v-for="(synonym,i) in row.synonyms">
<input type="text" class="form-control" v-model="row.synonyms[i]" />
</div>
<br>
<h3>
The text below should change if yout type inside the textboxes:
</h3>
<p>
{{ JSON.stringify(row)}}
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
The correct way to do it is to use an index, which vue.js provides in loops:
<div class="form-group" v-for="(synonym, index) in row.synonyms">
<input type="text" class="form-control" v-model="row.synonyms[index]" />
</div>
https://jsfiddle.net/m14vd89u/1/
This is the recommended way that Vue.js wants you to do it by using an index (synonym, index):
https://v2.vuejs.org/v2/guide/list.html
<div class="form-group" v-for="(synonym, index) in row.synonyms">
<input type="text" class="form-control" v-on:blur="onItemsChanged(synonym)" v-model="row.synonyms[index]" />
</div>
If you wanted to do it another way you could introduce a method v-on:blur:
new Vue({
el: "#app",
data: {
row: {
synonyms: [
"abc",
"def",
"ghj",
]
}
},
methods: {
onItemsChanged (synonym) {
// do something with array
}
}
})

How to implement iterated, array-filling Angular 2 inputs?

I want to be able to add/remove items in an order and have them aggregate into an array to be sent to the backend. The data will look like:
CustomerName: Billy
Orders: [Pizza, Burger, Sushi]
Can't find any SO answers or documentation that gets into iterated input binding. Anyone attempted this? Template code:
<div>
<input
type="text"
name="name"
title="name"
placeholder="Customer Name"
[(ngModel)]="customerName"/>
</div>
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[index]"/>
</div>
inside the Add New button's click function:
...firebaseStuff... .push({name: name, order: this.itemsInNewOrder})
unfortunately, this doesn't work. Thanks in advance! :)
Edit 1: There are 2 buttons that trigger (respectively):
incrementItemsInNewOrder() {
this.itemsInNewOrder.push("")
}
decrementItemsInNewOrder() {
this.itemsInNewOrder.pop()
}
I can see one problem. You should use the variable i that you have declared in template.
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[i]"/> <------ HERE
</div>
EDIT
angular seems to be doing change detection when typing into the inputs and renders them again, when that happens you lose the focus.
but if you wrap the values into objects and suddenly it works.
Component:
itemsInNewOrder = [{value: 'Soda'}, {value: 'Burger'}, {value: 'Fries'}];
template:
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[i].value"/>
</div>

Categories