Angular FormControl CheckBox selection marks every sibling - javascript

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)))

Related

How to solve ERROR TypeError: Cannot read property 'Checked' of undefined this error

Hi i need to remove multiple files uploaded from an array based on user selection in javascript or angular.........
I have tried with below code
First we have a files that are uploaded in an array and is displayed in checkboxes as shown below in code
<div *ngFor="let image of uploadedImages" style="margin-left:10%" >
<label class="container" style="font-size:14px">
{{image.name}} ModifiedDate: {{image.lastModifiedDate}}
<input type="checkbox" style="float:left" value="{{image.name}}" id="lifecheck"
[name]="image.name">
<span class="checkmark"></span> <br><br>
</label>
</div>
<div style="padding-left:34px;padding-bottom:3px;">
<button *ngIf="imagefilename.length" class="btn btn-danger" style="width:200px;padding-left:30px" (click)="dropzone.reset();resetimage(image.Checked)">
Reset Selected files
</button>
</div>
The user will click on the checkboxes that are to be removed and the click on the button displayed and
it calls a function as displayed below
resetimage(imageName:any) {
for(var index = 0; index<this.uploadedImages.length;index++){
if(document.getElementByName("lifecheck")[i].checked==true){
this.uploadedImages.splice(index,1);
}
}
}
So in this function ,only first file in an array is getting removed where the user has selected multiple files to remove
So please help me if there is any solution
Expected result :
to remove multiple files uploaded from an array based on user selection in javascript or angular
Actual result :
Getting error
In your typescript document.getElementByName("lifecheck") cannot find the element in the dom hence you getting the error. In your dom you are creating dynamic input elements with id ='lifecheck'. This is already the wrong way of assigning ids, since dom ids must be unique.
So to fix this you can change your view to assign dynamic unique ids to your input elements:
<div *ngFor="let image of uploadedImages;let i=index" style="margin-left:10%" >
<label class="container" style="font-size:14px">
{{image.name}} ModifiedDate: {{image.lastModifiedDate}}
<input type="checkbox" style="float:left" value="{{image.name}}" id="lifecheck_{{i}}"
[name]="image.name">
<span class="checkmark"></span> <br><br>
</label>
</div>
<div style="padding-left:34px;padding-bottom:3px;">
<button *ngIf="imagefilename.length" class="btn btn-danger" style="width:200px;padding-left:30px" (click)="dropzone.reset();resetimage(image.Checked,i)">
Reset Selected files
</button>
So you are creating input elements with id= "lifecheck_1" etc. Then you can pass this id to your typescript function and find the element:
resetimage(imageName:any,id:number) {
for(var index = 0; index<this.uploadedImages.length;index++){
if(document.getElementById("lifecheck_" + id).checked==true){
this.uploadedImages.splice(index,1);
}
}
}
NOTE: this should be the way to fix your error;

Form regneration on every interaction, angular forms

I'm having a problem with a Angular form. The problem is a checkbox, that contains some values (around 10). I have an item i push into this form with some allready selected values. So what I use the form to is editting/updating this item.
My checkbox right now can show which of the values in the checkbox were chosen before the edit. example here: https://gyazo.com/3cda89f3fc5c42de690fd8803274990b (hover to show)
But when I try to select a new checkbox value it just regenerates the whole checkbox every time, and I don't know why.
Maybe I'm filling the form on the wrong way, I'm creating the form like this:
<div class="form-group row">
<div class="col">
<label for="">Typer af data der indhentes:</label>
<div formArrayName="DataTypes"
*ngFor="let test of this.createWhatItemData().controls; let j=index"
class="form-group">
<div>
<div class="form-check">
<label class="form-check-label">
<input type="hidden" />
<input type="checkbox" class="form-check-input" [checked]="test.value.selected" />
{{whatItemDataTypes[j].Name}}
</label>
</div>
</div>
</div>
</div>
</div>
and then it is initialized and filled like this:
private initFormWhatComponent() {
this.form2 = this.formBuilder2.group({
ConsentWhatItemDirection: this.whatItem.ConsentWhatItemDirection,
ConsentWhatItemType: this.whatItem.ConsentWhatItemType,
OrganizationIdentifier: this.whatItem.OrganizationIdentifier,
Name: this.whatItem.Name,
Description: this.whatItem.Description,
DataTypes: this.formBuilder2.array(this.whatItem.DataTypes)
});
this.addWhatItemFormGroupWhatComponent(this.whatItem);
}
This is to get the allready selected values into my checkbox, and if i console log eg. "test" in this function it logs every time i interact with the form.
createWhatItemData() {
let _formArray = this.formBuilder2.array(
this.whatItemDataTypes.map(s => {
return this.formBuilder2.group({
selected: this.whatItem.DataTypes.some(x => x.Id == s.Id),
Id: s.Id,
});
})
);
return _formArray
}
The values that are availible to choose is fetched from the database, and are then merged together with the item values sent to the form.
can anyone help me with fixing the checkbox so I can select new values and then update my item?
Thanks in advance.
private initFormWhatComponent() {
this.form2 = this.formBuilder2.group({
ConsentWhatItemDirection: this.whatItem.ConsentWhatItemDirection,
ConsentWhatItemType: this.whatItem.ConsentWhatItemType,
OrganizationIdentifier: this.whatItem.OrganizationIdentifier,
Name: this.whatItem.Name,
Description: this.whatItem.Description,
DataTypes: this.formBuilder2.array(this.whatItem.DataTypes)
});
this.addWhatItemFormGroupWhatComponent(this.whatItem);
//return anything in here..
}

Build string map in JS from checkboxes using jquery

I'm still learning Jquery and am trying to figure out how to build a string containing some checkbox inputs and a parent title. I have a repeating table that is basically just a title wrapped in a tag and a list of inputs as children a few layers beneath that. I want to only grab h4 titles that have at least 1 child checkbox selected, and then the names of those checkboxes along with that h4 title. basically something like this:
{(h4 value1 here),
({selected checkbox name 1,
selected checkbox name 2})
},
{(h4 value3 here),
({selected checkbox name 1,
selected checkbox name 3})
}
Here's my current html for this table being built.
<div class="specialClass" id="categoryBox">
<c:forEach items="${searchCategories}" var="cat">
<div class="col4">
<h4><span class="categorySpan">${cat.key.description}</span></h4>
<p class="stack">
<c:forEach items="${cat.value}" var="subCats">
<label>
<input class="cat" type="checkbox" name="searchCategoryBoxes" value="${subCats}"/>
${subCats}
</label>
</c:forEach>
</p>
</div>
</c:forEach>
</div>
I'm able to add names/classes/IDs as needed, but am not really sure where to start. Any pointers on which articles to read to help me figure out jquery selectors? Or alternatively any pointers on how I can solve this problem? :)
I used some of daddygames answer and modified it to get the following:
var searchCategories =
$("input[name='searchCategoryBoxes']:checked")
.parents('div[class="col4"]')
.map(function(){
var checked = false;
var subCatStr = '{' +
$(this).find('input[type="checkbox"]:checked')
.map(function() {
checked = true; return this.value;
}).get().join(',') + '}';
if (checked) {
var catStr = '{' +
$(this).find('span[class="categorySpan"]')
.html() + ',' + subCatStr + '}';
return catStr;
}
// should never get here
return '';
}).get().join(',');
on the following html block
<div id="categoryBox">
<c:forEach items="${searchCategories}" var="cat">
<div class="col4">
<h4>
<span class="categorySpan">
${cat.key.description}
</span>
</h4>
<c:forEach items="${cat.value}" var="subCats">
<label>
<input type="checkbox" name="searchCategoryBoxes" value="${subCats}"/>
${subCats}
</label>
</c:forEach>
</div>
</c:forEach>
</div>
This returned the result I was looking for.

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>

Angular-js - Populating Checkbox and track it based on JSON file

I have a nested Objects in JSON, and I need to populate the checkbox based on what comes in (dynamic) from JSON file, meaning, I wouldn't know in advance the name of the fields, or how many elements there could be. Here is a sample, but there could be more child and each child could have more or less item in it.
{
"Parent":{
"Child" :
{
"Child_01" : {
"description_01":false,
"description_02":false,
"description_03":false,
"description_04":false,
"description_05":false
},
"Child_02" :
{
"something_01":false,
"something_02":false,
"something_03":false,
"something_04": false
},
"Child_03" :
{
"things_01":false,
"things_02":false,
"things_03":false,
"things_04":false,
"things_05":false
}
}
}
}
Now, I need to populate a drop down from it, (child_01, child_02, child_03....) and when user choose one of them, I need to display checkboxes of all its properties. And of course be able to keep track of the chosen one.
Here is what I have.
$scope.children = response.data.parent.child;
$scope.childrenList = [];
angular.forEach($scope.children, function(value1, key1){
$scope.childrenList.push(key1);
});
and html:
<div ng-repeat="(key, data) in children">
<input ng-model="childrenListModel" type="checkbox" name="{{child}}" value="{{child}}">{{child}}</input>
</div>
Nothing works the way I intend to. Any help would be appreciated.
You probably need several nested ng-repeats. Have a look at this working plunker: http://plnkr.co/edit/K92JI7UlW9h6gh8SPeU5?p=preview
<div ng-repeat="child in children.Parent.Child">
<div ng-repeat="options in child">
<div ng-repeat="option in options">
<div ng-repeat="(key, val) in option">
<label for="{{key}}">
{{key}}
<input name="{{key}}" type="checkbox" ng-model="option[key]" />
</label>
</div>
</div>
<hr />
</div>
</div>

Categories