Issue
Below shows that the string value works however if my input is a number it doesn't work. Any ideas aside from making a variable a string?
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<p>Model: {{model | json}}</p>
NOT WORKING<br/>
<input type="radio" name="foo" value="1" [(ngModel)]="model.foo" kendoRadioButton />
<input type="radio" name="foo" value="2" [(ngModel)]="model.foo" kendoRadioButton />
<input type="radio" name="foo" value="3" [(ngModel)]="model.foo" kendoRadioButton />
<br/>
WORKING<br/>
<input type="radio" name="bar" value="1" [(ngModel)]="model.bar" kendoRadioButton />
<input type="radio" name="bar" value="2" [(ngModel)]="model.bar" kendoRadioButton />
<input type="radio" name="bar" value="3" [(ngModel)]="model.bar" kendoRadioButton />
`
})
export class AppComponent {
public model = {
foo: 3,
bar: "2"
};
}
Solution
Instead of using [(ngModel)] for two-way binding, you could implement the two-way binding yourself by stringifying the setting, and handling the change events.
Each input for a numeric type would look like this:
<input type="radio" name="foo" value="1" kendoRadioButton
[ngModel]="model.foo.toString()"
(ngModelChange)="onFooChanged($event)" />
Your event handler in your component would look like this:
onFooChanged(value) {
this.model.foo = parseInt(value);
}
Without knowing what's going on behind the scenes with [(ngModel)], I assume it is doing a strict equality check for boolean types such as radio buttons.
DEMO: https://stackblitz.com/edit/angular-w3xwmx
Creating a reusable input
Creating an event handler per property would quickly get tedious if you have several of these. Alternatively you could create your own component that wraps this functionality.
number-radio.input.component.ts
import { Component, Input, forwardRef, ChangeDetectorRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
@Component({
selector: 'number-radio-input',
templateUrl: './number-radio-input.component.html',
providers: [
{ provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NumberRadioInputComponent),
multi: true }
]
})
export class NumberRadioInputComponent implements ControlValueAccessor {
@Input() name: string;
@Input() value: string;
model: string;
private _value: number;
private onChangeCallback: (value: number) => void = () => { };
onModelChange(): void {
this._value = parseInt(this.model, 10);
this.onChangeCallback(this._value);
}
registerOnChange(fn: (value: number) => void): void {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any): void {}
writeValue(val: number): void {
this._value = val;
this.model = val ? val.toString() : '';
}
}
number-radio-input.component.html
<input type="radio" [name]="name"
[value]="value"
[(ngModel)]="model" (ngModelChange)="onModelChange()" />
component.html
<number-radio-input [(ngModel)]="model.foo" value="1" name="foo">
</number-radio-input>
You would need to pass in additional properties if you wanted to configure the input differently, but at least this will allow you to bind to your model directly.
Answered By - Kurt Hamilton
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.