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

18,133

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 id="{{status}}">

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.

Share:
18,133

Related videos on Youtube

st_clair_clarke
Author by

st_clair_clarke

Updated on June 04, 2022

Comments

  • st_clair_clarke
    st_clair_clarke almost 2 years

    Seasons greetings everyone!

    I have the following code that constructs a single radio-button based on the materialize-css framework http://materializecss.com/forms.html#radio

    <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

  • st_clair_clarke
    st_clair_clarke over 7 years
    Great, and thanks. Two small tweaks I had to make to get it running - both id on the input and for on the label are attributes, NOT properties. Hence I had to prefix both with attr for it to work. See EDIT1 above for what works for me. Thanks
  • st_clair_clarke
    st_clair_clarke over 7 years
    Actually, only a single tweak is necessary - the one for label since id is both a property and an attribute.
  • adriancarriger
    adriancarriger over 7 years
    I just found out that it's only needed if you're using an Angular 2 version that is less than 2.2.0.. I was pretty confused at first, and it turns out they added this as a feature recently. Thanks for pointing it out as it led to some fun learning about the framework!

Related