Add a value to the i variable of Angular's ngFor - javascript

I want to create two rows of five inputs using ngFor. I want to store the inputs in an array so I figured I would use the index in the ngModel. However, when I try to add a value for the second row to the let i = index, I get Template parse errors.
<div class="row" *ngFor="let row of [0,5]">
<div class="col-md-5ths" *ngFor="let number of [0,1,2,3,4]; let i = index + row">
<input type="text" [(ngModel)]="input[i]">
{{input[i]}}
</div>
</div>
I tried some variations with a ternary operator and ngForOf, but to no success. It seems Angular is a lot stricter than AngularJS in this regard.
Plunker here.
Any suggestions?

It can be achieved so:
<div class="col-md-5ths" *ngFor="let number of [0,1,2,3,4]; let i = index">
<input type="text" [(ngModel)]="input[i+row]">
{{input[i+row]}}
</div>

Related

Not clearing the input (text) field value after Add / Remove Multiple Input Fields Dynamically

I am able to dynamically Add or Remove multiple input fields, But the issue is once I have added items and enter some values in the input fields and remove it using delete button, values are not getting cleared, i have tried to empty my array for that index as well but it is not working. Any suggestions please?
I appreciate your help!
Here is my html code:
<div class="row">
<div>
<button mat-raised-button (click)="test()">Add </button>
</div>
<div *ngFor="let value of fieldArray; let i = index">
<mat-form-field >
<input matInput value="{{getDataValue(i)}}" (focusout)="onFocusOut($event)" name ="test">
</mat-form-field>
<button mat-raised-button class="btn btn-danger btn-sm " (click)="remove(i)">Delete</button>
</div>
</div>
code in my .ts file:
fieldArray: Array = [];
remove(i: number) {
this.fieldArray.splice(i,1);
}
test(){
this.fieldArray.push(this.fieldArray.length);
}
With TrackBy, Angular is able to detect which items are deleted or added to an array, using a unique identifier. So, only the items added or removed have to be updated in the DOM.
Like below code for view:
<div *ngFor="let value of fieldArray; let i = index; trackBy: trackByFn">
Below code for .ts file:
trackByFn(index, item) {
return index; // or item.id
}

Angular FormControl CheckBox selection marks every sibling

StackBlitz: http://stackblitz.com/edit/angular-jul7bv
I am having trouble with Angular FromControl, that are being created dynamicly based od passed data.
My list displays Groups and Subgroups of specific Data, everything works almost perfectly fine, but whenever I check subgroup, every of its sibling is being marked and i am unable to come up whats wrong.
Thats my html:
<div *ngFor="let chapter of checkboxControlLabels; let i = index;">
<div class="input-checkbox-subgroup-list__checkbox">
<div class="input-checkbox">
<input type="checkbox" [attr.id]="chapter.id + '_checkboxControl_' + i"
[formControl]="getChapterControl(i)" />
<label [attr.for]="chapter.id + '_checkboxControl_'+ i">{{ chapter.title }} </label>
</div>
</div>
<div class="input-checkbox-subgroup-list__checkbox" *ngFor="let chart of chapter.charts; let x = index;">
<div class="input-checkbox chart">
<input type="checkbox" [attr.id]="chart.title + '_checkboxControl_' + x" [formControl]="getChartControl(i, x)" />
<label [attr.for]="chart.title + '_checkboxControl_' + x">{{ chart.heading }} </label>
</div>
</div>
</div>
And this is how I am mapping specific FormControl :
getChartControl(chapterIndex: string, chartIndex: number) {
return this.data.controls[chapterIndex].get('charts').controls[chartIndex];
}
As you can see on below image when I check subgroup, there is 11 selected and I have no idea how thats possible.
More intresting thing is that this doesnt apply to groups... So if I would check First group there would be only one selected...
This is FormGroupModel that I am using later on:
this.chapterChartsData.forEach(chapters => {
dataForm.push(new FormGroup({
chapter: new FormControl(false),
charts: new FormArray(Array(chapters.charts.length).fill(new FormControl(false)))
}))
});
Apparently problem was with populating list of form controls like that :
charts: new FormArray(Array(chapters.charts.length).fill(new FormControl(false)))

ngModel is reflecting to all textareas

I have multiple textareas (looping with ngFor and adding new divs with textareas inside). What i need is for every textarea to have separate ngModel and i don't want to directly bind this to property from object in dataArray - for example:
[(ngModel)]='data.note' or [(ngModel)]='data.feedback' .
This works but I don't have feedback property in dataArray so it won't for work for second textarea.
For example with my current implementation change in one textarea is reflecting in all other textareas. I tried with index approach but getting error:
ERROR TypeError: Cannot read property '1' of undefined
<div *ngFor="let data of dataArray; let index=index;trackBy:trackByIndex;">
<div class="card-body">
<form class="form">
<div class="form-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<textarea name="note" [(ngModel)]='selectedNote' class="form-control"
rows="2"></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<textarea name="feedback" [(ngModel)]='selectedFeedback' class="form-control" rows="4"></textarea>
</div>
</div>
</div>
</div>
</form>
</div>
With current code if i add some text in first textarea with name 'note' that change is reflected for all textareas with name 'note'. As mentioned tried with adding
[(ngModel)]='selectedFeedback[index]' but i am getting error.
Also tried with giving different names to textareas:
<textarea name="note{{index}}" [(ngModel)]='dataArray[index]' rows="2"></textarea> OR
<textarea name="note{{index}}" [(ngModel)]='selectedNote' rows="2"></textarea>
but change is reflecting for each textarea again.
You can try it with any array, I am using data(n) function to return an Array of length n. In this example it's just for iteration
<div *ngFor="let item of data(8); let i = index">
<textarea [(ngModel)]='values[i]'></textarea>
</div>
// To reflect changes
<div *ngFor="let item of data(8); let i = index">
<div>{{ values[i] }}</div>
</div>
With TS
export class AppComponent {
values = [];
data(n) {
return Array(n);
}
}
Working example in Stackblitz.com
ngModel binds with the name property. So if you want to use multiple textarea try using different name attribute. You can iterate over like -
<ng-container *ngIf="let data of dataArray; index as i">
<textarea name="feedback_{{i}}" [(ngModel)]='selectedFeedback' class="form-control" rows="4"></textarea>
</ng-container>

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>

Expression in ng-model AngularJS

I need to execute an expression inside ng-model.
I have an array of integers which is shown in a list and input fields needs be generated on click of each item. All input fields should carry a generated value of ratio having base as 1. I also need to get the sum of numbers in the input field since the user can change the value.
My Code for this is
<div class="row" ng-repeat="kpi in SelectedKpiModel">
<div class="small-2 columns" ng-click="View.RemoveSelectedKPI($index)" style="margin-top:0.5em;border:ridge;padding-bottom: 1em; padding-top:0.5em; text-align:center"><span class="fa fa-scissors"></span></div>
<div class="small-4 columns" style="margin-top:0.5em;border:ridge;padding-bottom: 1em; padding-top:0.5em; text-align:center">
{{kpi.id}}
</div>
<div class="small-4 columns" style="float:left;margin-top:0.5em;border:ridge; padding:0em">
<input type="number" value="{{1/SelectedKpiModel.length}}" />
</div>
</div>
How do I get the count of all the field values if user changes or how do I store the value of each field and retrieve if need ?
I tried like ng-model="{{1/SelectedKpiModel.length}}" but it gave me error.
Thanks.
You can use something like this -
<input type="number" ng-model="getLength()" />
and your function -
$scope.getLength = () => {
return 1 / $scope.SelectedKpiModel;
}

Categories