Reputation: 456
I have some problem making a checkbox works in a dynamic form using Angular 4.
On firefox, when checking the checkbox, the value I get is 'on'
in place of true
. And when unchecking it, the value is still there and not set to false
or ''
.
On chrome, it doesn't even seem to work...
I have created an example bases on the Angular dynamic form tutorial.
I have added a new file named question-checkbox.ts
to manage a checkbox:
import { QuestionBase } from './question-base';
export class CheckboxQuestion extends QuestionBase<boolean> {
controlType = 'checkbox';
type: string;
constructor(options: {} = {}) {
super(options);
this.type = 'checkbox';
}
}
Then, I have updated the dynamic-form-question.component.html
to use this new type:
<div [formGroup]="form">
<label [attr.for]="question.key">{{question.label}}</label>
<div [ngSwitch]="question.controlType">
<select [id]="question.key" *ngSwitchCase="'dropdown'" [formControlName]="question.key">
<option *ngFor="let opt of question.options" [value]="opt.key">{{opt.value}}</option>
</select>
<input *ngSwitchDefault [formControlName]="question.key" [id]="question.key" [type]="question.type" />
</div>
<div class="errorMessage" *ngIf="!isValid">{{question.label}} is required</div>
</div>
And, I have updated the dataset in question.service.ts
:
import { Injectable } from '@angular/core';
import { DropdownQuestion } from './question-dropdown';
import { QuestionBase } from './question-base';
import { TextboxQuestion } from './question-textbox';
import { CheckboxQuestion } from './question-checkbox';
@Injectable()
export class QuestionService {
getQuestions() {
let questions: QuestionBase<any>[] = [
new DropdownQuestion({
key: 'brave',
label: 'Bravery Rating',
options: [
{ key: 'solid', value: 'Solid' },
{ key: 'great', value: 'Great' },
{ key: 'good', value: 'Good' },
{ key: 'unproven', value: 'Unproven' }
],
order: 3
}),
new TextboxQuestion({
key: 'firstName',
label: 'First name',
value: 'Bombasto',
required: true,
order: 1
}),
new TextboxQuestion({
key: 'emailAddress',
label: 'Email',
type: 'email',
order: 2
}),
new CheckboxQuestion({
key: 'sideksick',
label: 'Sidekick',
order: 3
})
];
return questions.sort((a, b) => a.order - b.order);
}
}
Lastly, I have updated the dynamic-form.component.html
to display the current state of the form:
<div>
<form [formGroup]="form">
<div *ngFor="let question of questions" class="form-row">
<df-question [question]="question" [form]="form"></df-question>
</div>
</form>
<p><strong>Current state</strong><br>{{form.value | json}}</p>
</div>
So my question would be: How should I do to be able to use checkboxes inside an Angular 4 dynamic form, and be able to get a correct value?
As for why I need to use a dynamic form, it is because I am generating my form based on a JSON coming from an outside service which describe it.
Upvotes: 0
Views: 758
Reputation: 456
It seems there is a really strange behavior which cause this problem with Angular 4.x.
Writing this won't work:
<input *ngSwitchCase="'checkbox'" [formControlName]="question.key" [id]="question.key" [type]="'checkbox'" />
But writing this does work:
<input *ngSwitchCase="'checkbox'" [formControlName]="question.key" [id]="question.key" type="checkbox" />
The only difference is that we don't use Angular template functionalities ([type]="question.type"
, [attr.type]="question.type"
or type={{question.type}}
) to write the content of type
, and so we only use the native type
from HTML.
This seems like a bug to me...
Here the fix on Plunker.
The solution above is the only one you should consider.
I found an hint from the answer of angular2-dynamic-form-checkbox.
I was missing the following part in the file dynamic-form-question.component.html
: [(ngModel)]="question.value" (change)="question.value = ckb.checked" #ckb
.
<select [id]="question.key" *ngSwitchCase="'dropdown'" [formControlName]="question.key">
<option *ngFor="let opt of question.options" [value]="opt.key">{{opt.value}}</option>
</select>
<input *ngSwitchCase="'checkbox'" [formControlName]="question.key" [id]="question.key" [type]="question.type" [(ngModel)]="question.value" (change)="question.value = ckb.checked" #ckb />
<input *ngSwitchDefault [formControlName]="question.key" [id]="question.key" [type]="question.type" />
It seems that in the case of a dynamic form, checkboxes aren't manage automatically, and so we need to update their value on change
in function of the checked
state of the checkbox.
Here the fix on Plunker.
Upvotes: 0