Using *ngFor for create a series of radio buttons for angular2 using materialize-css framework

Seasons greetings everyone!

I have the following code that constructs a single radio-button based on the materialize-css framework

<input name = 'group1' type = 'radio' id = 'test2'/> <label for = 'test2'>Yellow</label> 

My attempt at using *ngFor is shown below:

 statuses: string[] = [ 'Single', 'Married', 'Divorced', 'Common-law', 'Visiting' ]; <p>{{maritalStatus?.status}}</p> <div *ngFor = 'let status of statuses; let indx = index'> <input #widget class = 'with-gap' name = 'statusGroup' type = 'radio' id = 'status' [value] = 'status' [(ngModel)] = 'maritalStatus.status' (change) = 'radioBtnChange$.next(status)' /> <label for = 'status'>{{status}}</label> <p>{{status}}{{ indx}}</p> </div> 

All buttons are created but only the first button (Single) can be selected.

How can I get the series of button to function as radio-buttons are expected to do?

Thanks

1 Answer

Plunker

Why it's not working

The status variable in your *ngFor loop is not being used in the for attribute of your label or the id attribute of your input.

There are two options to fix this:

Template expressions

You can use a template expression by putting the attributes in square brackets like this:

<input [id]="status">

which is what you did (correctly) with the value attribute.

A template expression produces a value. Angular executes the expression and assigns it to a property of a binding target; the target might be an HTML element, a component, or a directive.

Interpolation

You can use interpolation by using double-curly braces like this:

<input>

More generally, the material between the braces is a template expression that Angular first evaluates and then converts to a string.

What's the difference?

Checkout this answer for an explanation on the differences between these methods.

Full Template Html

<h2>Current Status</h2> <p>{{maritalStatus?.status}}</p> <h2>Options</h2> <div *ngFor="let status of statuses; let indx = index"> <input #widget class='with-gap' name='statusGroup' type='radio' [id]='status' [value]='status' [(ngModel)]='maritalStatus.status' /> <label [for]='status'>{{status}}</label> </div> 

Full Component

import {Component} from '@angular/core'; import {Http} from '@angular/http' import {bootstrap} from '@angular/platform-browser-dynamic'; @Component({ selector: 'material-app', templateUrl: 'app.component.html' }) export class AppComponent { maritalStatus = { status: 'Nothing selected' }; statuses: string[] = [ 'Single', 'Married', 'Divorced', 'Common-law', 'Visiting' ]; constructor() { } } 

Update - Angular 2 versions < 2.2.0

If you're using an Angular 2 version that is less than 2.2.0 you need to explicitly set the label's for attribute like this:

<label [attr.for]='status'>{{status}}</label> 

because for is not a property of label elements.

Why?

Since Angular 2.2.0 (634b3bb), Angular maps the for attribute to the related htmlFor property.

It sounds like a lot of developers intuitively expected this, so they added it.

This was all pretty confusing for me at first, and this article by Pascal Precht really cleared up a lot of questions.

3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like