Using Angular, create mat-checkbox components that are dynamically generated and bound using

In my Offer class, I have a property called "units" which is an array of objects.

export class Offer {
   public propertyA: string;
   public propertyB: string;
   public units: Unit[];
}

export class Unit {    
    public code: string,
    public name: string,
    public checked: boolean
}

I am developing with Angular 2 and want to display these units as selectable checkboxes for the user. I am also utilizing angular material components.

The HTML implementation looks like this:

<div *ngFor="let unit of model.units; let i=index">
  <mat-checkbox [(ngModel)]="model.units[i].checked"
    id="units[{{i}}]" name="units[{{i}}]">
       {{ unit.name }}
  </mat-checkbox>                        
</div>    

To load the units property, I use the following:

this.model.units.push(new Unit("code1","name1", false));
this.model.units.push(new Unit("code2","name2", false));
this.model.units.push(new Unit("code3","name3", false));

However, when I submit the form, the checked property does not retain the selected values. What could be causing this issue?

Answer №1

To implement one-way binding, add [checked]="unit.checked" and remove ngModel, id and name attributes from your mat-checkbox.

If you want to achieve two-way binding, you can follow a similar approach used in this example:

In your HTML file:

<div *ngFor="let unit of model.units">
  <mat-checkbox [checked]="unit.checked" 
  (change)="valueChange(model.units, unit, $event)">
       {{ unit.name }}
  </mat-checkbox>                        
</div>

Add the following method to your component file:

valueChange(model.units, unit, $event) {
        // set the two-way binding for the specific unit with the event
        model.units[unit].checked = $event.checked;
    }

UPDATE: To enable two-way binding without explicit handling, ensure that each item in model.units has a checked property.

In your component file:

this.model.units.forEach(item => {
                       item.checked = false; // adjust as needed
                    });

In your HTML file:

 <div *ngFor="let unit of model.units; let i=index">
    <mat-checkbox [(ngModel)]="unit.checked" [checked]="unit.checked"                                                                                    
    name="{{i}}-name">                             
    </mat-checkbox>
</div>

If you also want to control the enable/disable options, you can add the following:

In your component file:

this.model.units.forEach(item => {
                       item.checked = false; // adjust as needed
                       item.disabled = true; // adjust as needed
                    });

In your HTML file:

<div *ngFor="let unit of model.units; let i=index">
        <mat-checkbox [(ngModel)]="unit.checked" [checked]="unit.checked"
         [disabled]="unit.disabled"                                                                                    
       name="{{i}}-name">
        </mat-checkbox>
    </div>

Answer №2

I have successfully tested this code in Angular 7.

It is important to ensure that each checkbox has a unique name.

<mat-grid-list cols="4" rowHeight="100px">
                    <mat-grid-tile *ngFor="let item of aspNetRolesClaims" [colspan]="1" [rowspan]="1">
                        <span>{{item.claimValue}}</span>
                        <mat-checkbox [(ngModel)]="item.claimValue" name="{{item.claimType}}">{{item.claimType}}</mat-checkbox>
                    </mat-grid-tile>
                </mat-grid-list>

Answer №3

After testing in Angular 7, I did not encounter any errors related to your question. Feel free to check out a live demo on this StackBlitz example. Here is my response:

To ensure functionality, be sure to assign a unique name to the ngModel bound input.

Here's an example using your code snippet:

<div *ngFor="let unit of model.units; let i=index">
  <mat-checkbox 
    [(ngModel)]="model.units[i].checked"
    id="units-{{i}}" 
    name="units-{{i}}" // instead of array notation
  >
      {{ unit.name }}
  </mat-checkbox>                        
</div> 

In personal practice, I avoid using array notation like units[{{i}}] as it can merge all fields together, although it doesn't seem to be causing issues in your current implementation.

Answer №4

If you find yourself unable to utilize [(ngModel)] in situations where a FormGroup is employed, here's an alternative approach. In this scenario, it is assumed that 'obj' represents a custom object with an 'IsSelected' property.

<mat-checkbox [checked]="obj.IsSelected"                                      
 (change)="onSelectionChanged($event, obj)">{{obj.Name}}
</mat-checkbox>

To manually update the 'obj.IsSelected' property within the 'onSelectionChanged' method.

public onSelectionChanged(arg: MatCheckboxChange, obj:any) {
 obj.IsSelected = arg.checked;
}

Answer №5

Here is an alternative approach that may offer a simplified solution. This method has been proven effective when used within a form group.

<form [formGroup]='formGroup'>
    <mat-checkbox [(ngModel)]="obj.IsSelected" [ngModelOptions]="{standalone:> true}">
        {{obj.Name}}
    </mat-checkbox>
</form>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process of determining if two tuples are equal in Typescript?

When comparing two tuples with equal values, it may be surprising to find that the result is false. Here's an example: ➜ algo-ts git:(master) ✗ ts-node > const expected: [number, number] = [4, 4]; undefined > const actual: [number, number] ...

Tips for extracting specific JSON response data from an array in TypeScript

I have an array named ReservationResponse, which represents a successful response retrieved from an API call. The code snippet below demonstrates how it is fetched: const ReservationResponse = await this.service.getReservation(this.username.value); The st ...

Maintaining scroll position in React Router v6

My website's homepage displays a user's feed. When a user clicks on one of the feed cards, they are taken to a different URL. However, when the user returns to the homepage, it automatically scrolls to the top. I am looking for a way to preserve ...

Emphasize a word in a Typescript text by wrapping it in an HTML tag

I've been experimenting with using HTML tags within TypeScript to highlight specific words in a sentence before displaying the sentence in HTML. Despite searching on StackOverflow for various solutions, I haven't been able to find one that works. ...

Issue with starting @mauron85/cordova-plugin-background-geolocation on Ionic 5 and Angular 9 platform

I'm facing a challenge with integrating the background geolocation plugin into my app. Here is the documentation link for reference: https://ionicframework.com/docs/native/background-geolocation Here's the snippet of my code that initiates the p ...

Solutions for Utilizing Generic Mixins in Typescript

As a newcomer to Typescript, I have encountered an issue with mixins and generics. The problem became apparent when working on the following example: (Edit: I have incorporated Titian's answer into approach 2 and included setValue() to better showcas ...

The global variable in TypeScript is not specified; it is initialized within the declaration `declare global{}`

In my TypeScript code, I'm facing a challenge when trying to add a global scope variable. In JavaScript (NodeJS), this process is straightforward: // index.js globalThis.helloWorld = 'Hello World!'; require('./log.js') // log.js c ...

Ways to resolve a 404 error on a live Angular application being hosted by NGINX

I am encountering an issue with my deployed application on a server where every time I refresh a specific page, I receive a NGINX 404 error. The application is running within Docker. Below is the configuration file for NGINX. server { listen 80; locat ...

Compiling TypeScript to JavaScript with Deno

Currently experimenting with Deno projects and looking for a way to transpile TypeScript into JavaScript to execute in the browser (given that TS is not supported directly). In my previous experience with NodeJS, I relied on installing the tsc compiler via ...

Creating a default option in a Select tag with React when iterating over elements using the map method

After learning that each element in the dropdown must be given by the Option tag when using Select, I created an array of values for the dropdown: a = ['hai','hello','what'] To optimize my code, I wrote it in the following ...

"An error occurs when attempting to access "this" in a static method as it

Just diving into the world of React and Typescript and currently exploring React hooks. Encountered a problem that's leaving me scratching my head. Here's the hook I'm using to fetch data: export const useFetch = <T>( fetchFunc: ( ...

Is there a way to extract only the desired array object from a post API response using Angular's filtering mechanism?

I'm utilizing the getSearchBank() post API and receiving this particular response from it. This API provides me with a list of all banks stored in the database. (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] 0: {bankId: '616c07ca9d ...

What is the best way to exclude an interface using a union type recursively in TypeScript?

I wish to recursively exclude types that are part of union types, and eliminate certain union types Here is an example. Normal and Admin should be considered as union types interface Admin { admin: never; } interface Normal { normal: never; } ...

Opening a new tab in Angular 6 from a component with freshly generated HTML (containing input data)

Hello everyone. I have a requirement where I need to open a new browser tab with formatted input data from a modal component. Here's an example code snippet that attempts to achieve this using ng-template: @Component({ template: '< ...

Deleting an element from an array in Mongodb using Angular

My question remains unanswered: Delete an element from an array of an array in MongoDb In the process of creating a basic MEAN application similar to Stack Overflow, I have encountered an issue. Within my application, there are articles with upvotes and d ...

Challenges with Angular observables

Struggling to make observables work has been quite the challenge for me lately. My code now resembles a chaotic battleground rather than the organized structure it once was. The dreaded "ERROR TypeError: Cannot read property 'map' of undefined" ...

The elements appear tiny while the resolution is excessively large on the Ionic mobile device

I recently finished developing an Ionic project and successfully compiled it for both iOS and Android. Surprisingly, everything seems to be working fine on Android devices but I am encountering issues on iOS and when viewing the project from Chrome's ...

Tips for ensuring your controls function properly and seamlessly when switching to another page

I utilized the instructions from this post to implement a slider. However, I encountered an issue with the controller when navigating to subsequent pages. While the controller functions correctly on the initial page, it duplicates the same values on the fo ...

"Exploring the best practice: Defining types in React with Typescript before or after

As a newcomer to typescript, I have noticed that some projects declare the type before the component while others declare it after the component. Can someone explain the differences between these approaches? export type TProps = { item: string; } expor ...

Synchronizing Form Data in Angular 5: Pass and Populate Dropdowns between Components

I have developed a unique form (material dialog modal) that allows users to create an account. When the user clicks on the Register button, their created account should appear in a dropdown menu without redirecting or reloading the current page. I am facin ...