Dynamic AngularJS Forms - javascript

I got a view in which lies the following <div>
<div ng-repeat="product in Product_List" ng-show="Product_List.length >=1">
<input type="text" ng-model="product.ProductCode" ng-value="CurrentProduct.ProductCode">
<input type="text" ng-model="product.ProductName" ng-value="CurrentProduct.ProductName">
</div>
Now push to the Product_List array, resulting in having the elements above repeated as follows,
$scope.Product_List.push({
"ProductCode": "",
"ProductName": ""
});
So far so good, but following is my problem,
How do i make an array as follows every time i add elements to the Product_List ?
[
{
"ProductCode" :"P1",
"ProductName" :"Coffee"
},
{
"ProductCode" : "P2",
"ProductName" : "Beer"
}
]

You can use the same product object for current value it will update the object value. http://jsfiddle.net/sudeep1049/jbj4movu/
<input type="text" ng-model="product.ProductCode" >
<input type="text" ng-model="product.ProductName">

Related

Vue js, how to bind input value from array?

i have a number field, that i want to bind value from an array like this :
<div v-for="p in products">
<input type="number" :value="carModel[p.name]" />
</div>
where p.name is a string (product name), car_a :
const app = Vue.createApp({
data() {
return {
products: {...},
carModel:[{car_a:4}, {car_b:2} ]
}
}
...
But this does not works, the input remains empty, while following runs without issue :
<div v-for="p in products">
<input type="number" :value="carModel" />
</div>
const app = Vue.createApp({
data() {
return {
products: {...},
carModel:4
}
}
...
So, my question is, how to bind the value properly from array if i have the key ?
thank you
First off, I wonder if your carModel array item object structure could be improved; perhaps better would be something like:
products: ["car_a", "car_b"],
carModel: [
{
name: "car_a",
value: 4,
},
{
name: "car_b",
value: 2,
},
{
name: "car_c",
value: 3,
},
]
I assume that the Strings held in the products array are a sub-set of the Strings in the carModel array of objects, and since you want an input that is reactive with the data, you will want the input's model to be the values held by each carModel object. So rather than v-for loop over the products array, v-for loop over the carModel but filter out the elements whose Strings are not held by the products array. Since we should not combine v-for with v-if, this filtering should be done in a computed property:
computed: {
filteredCarModel() {
return this.carModel.filter(cm => {
return this.products.includes(cm.name);
});
}
},
so then in the HTML template you can loop over the computed property:
<div v-for="cm in filteredCarModel" :key="cm.name">
<label :for="cm.name">{{ cm.name }} </label>
<input type="number" :id="cm.name" v-model="cm.value" />
</div>
This is key:
This will display proper values in the input elements, and these elements will remain reactive to the model such that changes to the inputs will cause changes to the data model, and visa-versa. Thus the display will be truly bound to the data model, which is what you're asking and what Vue.js is all about.
Here is a sample HTML showing that the data is in fact reactive:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<html>
<head>
<meta charset=utf-8" />
<title>Vue Example</title>
<script src="https://unpkg.com/vue#next"></script>
</head>
<body>
<h1>Vue Example</h1>
<div id="app">
<h2>Show Data</h2>
<div v-for="cm in carModel" :key="cm.name">
{{ cm.name }} : {{ cm.value }}
</div>
<h2>Change Data</h2>
<div v-for="cm in filteredCarModel" :key="cm.name">
<label :for="cm.name">{{ cm.name }} </label>
<input type="number" :id="cm.name" v-model="cm.value" />
</div>
</div>
<script>
Vue.createApp({
data() {
return {
products: ["car_a", "car_b"],
carModel: [
{
name: "car_a",
value: 4,
},
{
name: "car_b",
value: 2,
},
{
name: "car_c",
value: 3,
},
],
};
},
computed: {
filteredCarModel() {
return this.carModel.filter((cm) => {
return this.products.includes(cm.name);
});
},
},
}).mount("#app");
</script>
</body>
</html>
</html>
Note that if the products array is not a subset of the carModel array, if all the Strings present in products are also present in carModel name fields, then there will be no need to have a filteredCarModel() computed property.
change your carModel to hash
carModel: { 'car_a': 4, 'car_b': 2 }
because what you are trying to do is access array by string(which it should be number as index of the array)
Observations :
products should be an array to iterate via v-for.
As carModel is an array. You can not access object properties directly. Access it via index.
Working Demo :
new Vue({
el: "#app",
data: {
products: [{name: 'car_a'}, {name: 'car_b'}],
carModel:[{car_a: 4}, {car_b: 2}]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(product, index) in products" :key="index">
<input type="number" :value="carModel[index][product.name]"/>
</div>
</div>

Old Data not being overridden by new user input in vue component

I have a vue component that is performing a series of conditionals to check if there is previous data when editing a form. Since the form is being edited there is always previous data but if I type something into the input field and click the save button, my newly typed input is not being persisted but rather the same old data is remaining. I understand that it is happening because the v-if condition is always true but I cannot think of a way to modify the condition if the user types new data in to replace it. The original job is being passed in as a prop which contains the old/original data.
A conditional from my vue:
<div v-if="job.title">
<input :value="job.title" id="title" name="title" type="text" required>
</div>
<div v-else>
<input v-model="newJob.title" id="title" name="title" type="text" required>
</div>
props: {
route: String,
job: Object,
},
data() {
return {
newJob: {
title: ''
},
}
},
So when I type new information the v-model for the newJob is not being updated in the vue dev tools. How do I get the newJob field to update IF the user types something in, otherwise continue to save the old/original value that was in the edit form when the page loaded.
You only need
<input v-model="newJob.title" id="title" name="title" type="text" required>
and
props: {
job: Object,
},
data() {
return {
newJob: {
title: this.job.title || "",
},
};
},
One approach would be to use a property with an object as its default value rather than a prop and a data value:
<input :value="job.title" id="title" name="title" type="text" required>
and
job: {
type: Object,
default: function () {
return {
title: '',
}
}
},

How to create a multiple radio group in angular

How to create a multiple radio where there's a question and you will just choose Passed or Failed. it will not affect the other item when you choosing the passed or failed
for example:
Item 1 - What do you think? you will pass or fail? : *Passed * Failed
Item 2 - Your classmate anna will be pass or fail? : *Passed * Failed
Item 3 - Your best friend grade will be pass or fail? : *Passed * Failed
Item.ts file
class Item{
id : number;
question : string;
isPassed : boolean;
}
app.component.ts
export class AppComponent {
items : Item[]=[];
constructor(){
console.log("onitnit")
this.items.push({
'id':1,
'question': 'question1?',
'isPassed':false,
})
this.items.push({
'id':2,
'question': 'question2?',
'isPassed':false,
})
this.items.push({
'id':3,
'question': 'question3?',
'isPassed':false,
})
}
resultHandler(){
console.log(this.items);
}
}
app.component.html file
<div *ngFor = "let item of items" style="display : flex;">
{{item.question}}
<form style="margin-left:20px">
passed: <input type="radio" name="orders" [value]="item.id"/>
failed: <input type="radio" name="orders" [value]="item.id"/>
</form>
</div>
working demo
See console for final result generated.
Multiple radio group with reactive form.
HTML:
<form [formGroup]="form">
<div *ngFor="let que of questions">
<span>{{que.question}}</span>
<mat-radio-group [formControlName]="que.id" aria-label="Select an option">
<mat-radio-button value="true">Passed</mat-radio-button>
<mat-radio-button value="false">Failed</mat-radio-button>
</mat-radio-group>
</div>
<pre>{{form.value | json}}</pre>
</form>
TS:
form: FormGroup;
questions = [{
id: "1",
question: "What do you think? you will pass or fail?",
result: false
},
{
id: "2",
question: "Your classmate anna will be pass or fail?",
result: false
},
{
id: '3',
question: "Your best friend grade will be pass or fail?",
result: false
}]
constructor(private fb: FormBuilder) {
this.form = this.fb.group({ });
this.questions.forEach(question => {
this.form.addControl(question.id, this.fb.control(null, Validators.required));
})
}
stackblitz link : https://stackblitz.com/edit/angular-pyfprq
Created a example for your functionality
Stackblitz example
You can set name attribute unique for each group. Let say -
<input type="radio" name="{{index}}"/>

Update model inside ngFor

How do you update a model with array of objects inside ngFor? My code ignores all updates.
<div *ngFor="let item of model.items; let i = index">
<input name="names-{{i}}" [(ngModel)]="item.name" class="input" type="text">
<input name="values-{{i}}" [(ngModel)]="item.value" class="input" type="text">
</div>
Expected output:
model.items = [{ name: ... value: ...}, { name: ... value: ...}, ...]
Use ChangeDetectorRef's markForCheck() method for updating the model if it does not change when the data changes.

Vue Js - Radio inputs not updating model value

I have an object containing questions data.
I'm looping through these in the view and then aiming to update the objects 'answer' value.
The questions come from an API and are structured as:
[
{
"id": 1,
"choices": [
// choices
],
"created_at": "2016-12-08 09:19:30",
"updated_at": "2016-12-09 15:29:14",
"answer": []
},
]
They don't come from the API with an answer value but I have added it in the js file.
I then show the question answers in another loop:
<div v-for="(choice, index) in question.choices" class="input-row">
<input type="radio" v-model="question.answer" value="choice.value"/>
</div>
I then out the answer into the view:
#{{ question.answer }}
I can see it's an empty array, but when selecting the radio button the array isn't updated like I thought it would. Any ideas?
Your input have wrong markup to bind the value with a Vue data property.
<div v-for="(choice, index) in question.choices" class="input-row">
<input type="radio" v-model="question.answer" v-bind:value="choice.value"/>
</div>

Categories