Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

two-way binding on checkbox ngFor Angular2

I am creating an Angular2 project and having a problem with two-way binding for a checkbox.

I have a class called listItem and List like that:

export class ListItem {
  public count: number;
  public value: string;
  public checked: boolean;

  constructor(count: number, value: string, checked: boolean) {
    this.count = count;
    this.value = value;
    this.checked = checked;
  }
}

export class MyList{
  public category: string;
  public listItem : ListItem [];

  constructor(category: string, listItem : ListItem []) {
    this.category = category;
    this.listItem = listItem ;
  }
}

and I am calling the list from Azure search which is working correctly. the problem is when I just set the value to a checkbox.

<div *ngFor="let list of myList; let listIndex = index;">
  <div *ngFor="let item of list.listItems; let itemIndex = index;">
    <input type="checkbox" [name]="list.category + item.value"
         (change)="item.checked = !item.checked"
         [ngModel]="item.checked" />
  </div
</div>

but the value is always false also onClick. I tried to use [(ngModel)] but did not work also. I also tried to make a function:

(change)="oncheck(listIndex, itemIndex)"

oncheck(listIndex: number, itemIndex: number) {
   this.myList[listIndex].listItems[itemIndex].checked =  
           !this.myList[listIndex].listItems[itemIndex].checked;
  } 

but I received this error:

Cannot assign to read-only property 'checked' of object '[object Object]'

why is that and how to fix it? thank you

like image 387
Samy Sammour Avatar asked Mar 02 '26 05:03

Samy Sammour


1 Answers

You could use the material2 md-checkbox directive to create styled elements. In my opinion that is not really two-way binding, its just a combination of 1 way binding in both directions (template - data source and data source - template)

UPDATE: I created a small plnkr to reproduce your situation: http://plnkr.co/edit/cr7TokiqSaBGli7mgCBM

@Component({
  selector: 'my-app',
  template: `
    <div *ngFor="let element of elements; let i = index;">
    <span>Val: {{element}}</span>
      <input type="checkbox"
       [checked]="element" (change)="handleChange(element, i)">
    </div>
  `,
})
export class App {
  elements= [
    false,
    true,
    false,
  ]:

  handleChange(val: boolean, index: number){
    console.log("Index: "+index);
    console.log("Val:  "+val);
    this.elements[index] = !val;
  }

The elements in the list are correctly rendered, but the change events will in some cases modify the values of incorrect positions in the elements array. Ill take a furhter look later

UPDATE: refactored plnkr

Please check: http://plnkr.co/edit/Ich0g5kzSiQINZjh3VYo

I made some changes to the plnkr that u sent me.

I changed the iteration variables from const to let (considering that their values arent constant during execution of the loops).

As I mentioned before, most likely there are 2 posibilities: the classes in .ts are being transpiled in a wrong way to .js (class members are being setted as readonly by default), or there is something wrong in the way that you are manually mapping the values to class instances.

like image 139
Jota.Toledo Avatar answered Mar 03 '26 19:03

Jota.Toledo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!