angular: Binding to [name] on radio inputs does not provide browser-default tab interaction

I’m submitting a … (check one with “x”)

[x] bug report => search github for a similar issue or PR before submitting

Current behavior When the the name attribute of a radio input is bound using [name]='name', it appears that the actual name attribute is not set with the bound value. This causes incorrect tab behavior for groups of radios. If I have a component with 3 radios, and repeat that component 3 times, then all 9 radios behave as if they had the same name (they collectively act as a single tab stop, and the arrow keys can be used to navigate between all 9 when any radio is focused). See https://plnkr.co/edit/SXxIxZM1BuMsnAZnN1UF?p=preview

When binding to [attr.name], tab/arrow key navigation works as expected, but other radios that share the same value are also selected. I.E. when selecting Option 1 in group 1, Option 1 is selected in groups 2 and 3 as well. However, this appears to not effect the value of the FormControl, the selected value and the selected radio become out of sync. See: https://plnkr.co/edit/5jHshpyQHezLqZEXqz5v?p=preview

When binding to both [attr.name] and [name] I get the expected behavior, but it seems like I should only need to bind to one or the other. See: https://plnkr.co/edit/7ZnsSzTCuyiufCdjX5zN?p=preview

Expected behavior

Binding to [name] should set the input’s name attribute so that the correct tab behavior is preserved. In the above example, each component’s 3 radios should act as a single tab stop, and using the arrow keys should cycle between each of the component’s 3 radios.

If binding to both [name] and [attr.name] is required, it should probably be documented, maybe in FormControlDirective?

What is the motivation / use case for changing the behavior? My app supports custom radio fields, so the number of fields and their options are all runtime values. I’m trying to create a reusable radio-group which accepts bindings to name, options, and formControl.

  • Angular version: 2.0.0
  • Browser: all

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 5
  • Comments: 17 (5 by maintainers)

Commits related to this issue

Most upvoted comments

@adharris Thanks for reporting! Radio buttons are intended to be used with name or [name], but you’re correct that the normal name attribute isn’t mirrored. Using both name and [attr.name] is the workaround for now, but it’s confusing and not great for accessibility. The form control directives should handle the attribute mirroring for you. We’ll put it on the list.

@matod You’ll want to use formControlName if it’s part of the parent form or formControl if you’d like a standalone control that isn’t registered. The plunker appears to try to mix those by using formControl and also registering it. Worth noting that you’ll need to bind to [name] if you want the selection to work properly for both cases (and as mentioned above, also [attr.name] if you want the tab stops to work correctly).

Im having the same problem. When using dynamic binding of [name] the name attribute is not rendered in the dom. But the name attribute is necessary for browser autocomplete / remembering input data. Using [name] and [attr.name] together seems to be a workaround.

I want to add that this behavior depends on how you build the app.

I’ve noticed that if you turn off optimization in angular.json, then Angular will set the name property. If you turn on optimization, then Angular will not set the name property anymore.

As a workaround, you can create a new directive with the selector of ‘input[name]’ as follows:

import { Directive, ElementRef, Input } from '@angular/core';

@Directive({
  selector: 'input[name]'
})
export class NameAttrFixDirective {

  @Input() name: string;

  constructor(private element: ElementRef) {

  }

  ngOnInit(){
    this.element.nativeElement.setAttribute('name', this.name);
  }
}

This should add a name attribute in Dom to the respective element.

Thanks; I actually just tried binding to both [name] and [attr.name] at the same time, and it appears to be working as I expect; If this is the intended solution this can be closed, and I’ll update the original so it shows up in searches. Seems weird to need to bind to both though.