Keep dynamic table synced with model in AngularJS - angularjs

I have the following sample model:
{
a:{
x:0,
z:0,
f:1
},
b:{
x:"a",
u:"b"
}
}
Which I render into two different tables
<div class="col-sm-5">
<h1>A</h1>
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr ng-repeat="(key,value) in schema.a">
<td>
<input type="text" ng-model="key" required>
</td>
<td>
<input type="text" ng-model="value" required>
</td>
<td></td>
</tr>
</table>
</div>
<div class="col-sm-5 col-md-offset-2">
<h1>B</h1>
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr ng-repeat="(key,value) in schema.b">
<td>
<input type="text" ng-model="key" required>
</td>
<td>
<input type="text" ng-model="value" required>
</td>
<td></td>
</tr>
</table>
</div>
The tables are dynamic, which means I can add new rows to it.
Now when I change any values inside the table, they arenĀ“t synchronized with the model -> Editing not possible
What do I need to do to store changes automatically in the original
model?
If this is not possible, how can I get a Json Schema from my table
like the one the tables are rendered from, so that I only have to
overwrite the old one?

First off you can't dynamically change an object property name or key. So what you are trying to do with ng-model="key" simply won't work.
As far as the value part you should be using the object reference in your ng-model
<tr ng-repeat="(key,value) in schema.b">
<td>{{key}}</td>
<td>
<input type="text" ng-model="schema.b[key]" required>
</td>
<td></td>
</tr>
if you need to be able to edit the key then you need to change your data structure to an array of objects with each object having the same property names for keys

Related

Array Data Binding in VueJS

I need help in making my checkboxes in an array format. I have these codes:
<form #keyup="validate">
<div class="form-group">
<thead>
<th>Task Schedule</th>
<th>Notify Me</th>
<th>Email Me</th>
</thead>
<tbody>
<tr v-for="(row, index) in tableData.data" :key="index">
<td> {{ row.name }} </td>
<td><input type="checkbox" id="notify" name="notify" :value="tasks.id" v-model="data.notify"></td>
<td><input type="checkbox" id="email" name="email" :value="tasks.id" v-model="data.email"></td>
</tr>
</tbody>
</div>
</form>
Not sure though about the v-model of my checkboxes. because if I check even just one checkbox, the other boxes also gets checked. I think I need to add computed as well but Im not sure what to code. Thanks

How to output items from an array in angular

Im really new to angular. And I find that it is really hard to get an item from an array and output in the relevant html file in that component.
The below code shows the onClick function of the bill-item.component.ts file
arr: Array<any> =[];
itemArray: Array<any> =[];
onAddToBill(itemId:string, name:string , expireDate:string , quantity:string){
this.itemArray.push([itemId,name,expireDate,quantity]);
this.arr.push(this.itemArray);
console.log(this.arr);
}
And I need to output the item array on my bill-item.component.html which is shown below
<tbody>
<tr *ngFor="let itemArrays of arr">
<td *ngFor="let obj of itemArrays">{{obj[1]}}</td>
<td *ngFor="let obj of itemArrays">{{obj[0]}}</td>
<td><input type="number" class="is-center" id="number" value="1" style="width: 50%;" /></td>
<td *ngFor="let obj of itemArrays">{{obj[2]}}</td>
<td *ngFor="let obj of itemArrays">{{obj[3]}}</td>
</tr>
</tbody>
The below image shows the item list when I add the first item
But after adding the second item , the item list shows like this
Here all the items gets add up to the same row , I want to get each item in separate row , line after line.
Then I tried the below code
<tbody>
<tr *ngFor="let entries of arr">
<td>{{entries [1]}}</td>
<td>{{entries [0]}}</td>
<td><input type="number" class="is-center" id="number" value="1" style="width: 50%;" /></td>
<td>{{entries [2]}}</td>
<td>{{entries [3]}}</td>
</tr>
</tbody>
And this was the result. As ID has the entry[0] it was filled with all the instances in that array.
The below image shows my console.log(arr) result after adding 3 items
you can easily get values from "itemArray" rather than use "arr" and get the item details and print in table.
<table>
<tr *ngFor="let x of itemArray">
<td>{{x[0]}}</td>
<td>{{x[1]}}</td>
</tr>
</table>
like wise
you do not need to use *ngFor for each of entries as you are using array indexes like entries[1]
<tbody>
<tr *ngFor="let entries of arr">
<td>{{entries [1]}}</td>
<td>{{entries [0]}}</td>
<td><input type="number" class="is-center" id="number" value="1" style="width: 50%;" /></td>
<td>{{entries [2]}}</td>
<td>{{entries [3]}}</td>
</tr>
</tbody>
I tried this above code with following value of arr
arr = [['a','b','c','d'],['a1','b1','c1','d1']]
and got the result as
There is no need for iterating itemArrays. You can directly access element using the index.
Remove *ngFor of each itemArrays on each row.
<tbody>
<tr *ngFor="let itemArrays of arr">
<td>{{itemArrays[1]}}</td>
<td >{{itemArrays[0]}}</td>
<td><input type="number" class="is-center" id="number" value="1" style="width: 50%;" /></td>
<td >{{itemArrays[2]}}</td>
<td>{{itemArrays[3]}}</td>
</tr>
</tbody>
In td you are already accessing the items in the array, so you do not need to use *ngFor.
<tbody>
<tr *ngFor="let itemArrays of arr">
<td>{{itemArrays[1]}}</td>
<td>{{itemArrays[0]}}</td>
<td><input type="number" class="is-center" id="number" value="1" style="width: 50%;" /></td>
<td>{{itemArrays[2]}}</td>
<td>{{itemArrays[3]}}</td>
</tr>
</tbody>

AngularJS ui-utils password validation

I've got a problem with angular ui-utils, specifically ui-validate. I'm trying to supply a user with a password change form and to require "new password" and "confirm new password" to match, here:
<table class="table">
<form>
{{!!passwordForm.newPassword2.$error.validator}}
<tr>
<th>Current password: </th>
<td><input type="text" name="currentPassword" ng-model="passwordForm.currentPassword"></td>
</tr>
<tr>
<th>New password: </th>
<td><input type="password" name="newPassword" ng-model="passwordForm.newPassword"></td>
</tr>
<tr>
<th>Confirm new password:</th>
<td><input type="password" name="newPassword2" ng-model="passwordForm.newPassword2" ui-validate=" '$value==passwordForm.newPassword' " ui-validate-watch=" 'passwordForm.newPassword' "></td>
</tr>
<tr>
<td/>
<td>
<button type="button" ng-click="sendChangePassword()" ng-disabled="passwordForm.newPassword2.$error.validator" class="btn btn-primary">Save</button>
</td>
</tr>
</form>
</table>
and in my controller I have
$scope.passwordForm = {
currentPassword: "",
newPassword: "",
newPassword2: ""
};
The problem is, no matter whether or not newPassword and newPassword2 match, the save button stays enabled and {{!!passwordForm.newPassword2.$error.validator}} evaluates to false.
I've gone through several stackoverflow threads and other sources already, but I just can't figure out what's wrong with my code. Any help would be appreciated.
First make sure you have registered ui-utils properly by adding 'ui.utils' in your app registration like
angular.module("plunker", ['ui.utils']);
then there are some problems with the Html you have posted, first your form is nested inside of a table and this is not valid, so I moved it outside the table and I also provided the form a name
<form name="myForm">
<table class="table">
{{!!myForm.newPassword2.$error.validator}}
<tr>
<th>Current password:</th>
<td>
<input type="text" name="currentPassword" ng-model="passwordForm.currentPassword">
</td>
</tr>
<tr>
<th>New password:</th>
<td>
<input type="password" name="newPassword" ng-required="true" ng-model="passwordForm.newPassword">
</td>
</tr>
<tr>
<th>Confirm new password:</th>
<td>
<input type="password" name="newPassword2" ng-required="true" ng-model="passwordForm.newPassword2" ui-validate=" '$value==passwordForm.newPassword' " ui-validate-watch=" 'passwordForm.newPassword' ">
</td>
</tr>
<tr>
<td></td>
<td>
<button type="button" ng-click="sendChangePassword()" ng-disabled="myForm.newPassword2.$error.validator" class="btn btn-primary">Save</button>
</td>
</tr>
</table>
</form>
I also added ng-required to the two new password fields as that would be needed to not allow a blank password and finally in your buttons ng-disabled attribute reference the actual form name instead of your object to find the validator.
this should fix it, I have a working example here

Error in selecting many checkboxes in AngularJS

I have created a table from 2 different arrays in AngularJS that contain employees name and services and rest of the cells contain Checkboxes now I want get the ID's of selected Checkboxes that I have created another array in the controller,
but the view allows me to select only one Checkbox from many in the row
here is my Html
<form ng-submit="save()">
<table border="1">
<tr>
<td><strong>Services</strong></td>
<td ng-repeat="e in PBA">{{e.Name}}</td>
</td>
<tr ng-repeat="(index,i) in SOB">
<td>{{i.Name}}</td>
<td ng-repeat="e in PBA track by $index">
<input type="checkbox" name="cb" ng-true-value="{{e.Id}}_{{i.Id}}" ng-model="ids[index]" />
</td>
</tr>
</table>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" />
</div>
</form>

how to Avoid ng-repeat in <tr> for particular <td> - Angular Js?

I need to skip the ng-repeat for particular column.
My Code:
<tr ng-repeat="(lunches,price) in lunchTwo">
<td>
<label class="label_wraptext">{{lunches}}</label>
</td>
<td class="td_width">
</td>
<td>
<label>{{price}}</label>
</td>
<td style="padding-left:190px">
</td>
<td>
<select ng-controller="Quantity">
<option ng-repeat="key in notSorted(data)" ng-init="value = data[key]">
{{key}}
</option>
</select>
</td>
</tr>
I need to avoid binding the 'Select' control for all the rows.
Thanks in Advance,
Stephen.L
Suppose if you want to show the select control only for the first row, you can give a check using the index if it is equals ZERO, then show the select box, else not.
Please find the updated code below, check if it works for you.
<tr ng-repeat="(lunches,price) in lunchTwo">
<td>
<label class="label_wraptext">{{lunches}}</label>
</td>
<td class="td_width">
</td>
<td>
<label>{{price}}</label>
</td>
<td style="padding-left:190px">
</td>
<td>
<select ng-controller="Quantity" ng-show="$index==0">
<option ng-repeat="key in notSorted(data)" ng-init="value = data[key]">
{{key}}
</option>
</select>
</td>
</tr>

Resources