src/angular-forms.component.ts
OnInit
OnChanges
AfterViewChecked
selector | rb-angular-forms |
template |
|
Properties |
|
Methods |
|
Inputs |
Outputs |
constructor(changeDetectorRef: ChangeDetectorRef, translateService: TranslateService)
|
||||||||||||
Defined in src/angular-forms.component.ts:191
|
||||||||||||
Parameters :
|
groups
|
Type: |
Defined in src/angular-forms.component.ts:183
|
lang
|
Type:
Default value: |
Defined in src/angular-forms.component.ts:184
|
readOnly
|
Type:
Default value: |
Defined in src/angular-forms.component.ts:185
|
error
|
$event type: EventEmitter<Error>
|
Defined in src/angular-forms.component.ts:187
|
ready
|
$event type: EventEmitter<boolean>
|
Defined in src/angular-forms.component.ts:188
|
Public getAnswers |
getAnswers()
|
Defined in src/angular-forms.component.ts:280
|
Returns :
Object
|
Public getAnswersGroups |
getAnswersGroups()
|
Defined in src/angular-forms.component.ts:264
|
Returns :
Object
|
Public getForm |
getForm()
|
Defined in src/angular-forms.component.ts:248
|
Returns :
literal type
|
Public getGroupByCode | ||||||||
getGroupByCode(code: string)
|
||||||||
Defined in src/angular-forms.component.ts:228
|
||||||||
Parameters :
Returns :
Group<any>
|
Public hideQuestion | ||||||||||||
hideQuestion(question: Question
|
||||||||||||
Defined in src/angular-forms.component.ts:236
|
||||||||||||
Parameters :
Returns :
boolean
|
Public isDirty |
isDirty()
|
Defined in src/angular-forms.component.ts:256
|
Returns :
boolean
|
Public isPristine |
isPristine()
|
Defined in src/angular-forms.component.ts:252
|
Returns :
boolean
|
Public isValid |
isValid()
|
Defined in src/angular-forms.component.ts:260
|
Returns :
boolean
|
Public onChangeOptionSelect | ||||||||||||||||
onChangeOptionSelect(htmlFormControl: HTMLInputElement, formControl: FormControl, question: Select)
|
||||||||||||||||
Defined in src/angular-forms.component.ts:240
|
||||||||||||||||
Parameters :
Returns :
void
|
Public onError | ||||||||
onError(error: Error)
|
||||||||
Defined in src/angular-forms.component.ts:297
|
||||||||
Parameters :
Returns :
void
|
Public submit |
submit()
|
Defined in src/angular-forms.component.ts:244
|
Returns :
void
|
Public formGroup |
formGroup:
|
Type : FormGroup
|
Defined in src/angular-forms.component.ts:180
|
Public originalValueFormGroup |
originalValueFormGroup:
|
Type : Object
|
Defined in src/angular-forms.component.ts:303
|
Public status |
status:
|
Type : Status
|
Defined in src/angular-forms.component.ts:307
|
Public Status |
Status:
|
Type : Object
|
Default value : Status
|
Defined in src/angular-forms.component.ts:178
|
Public submitted |
submitted:
|
Type : boolean
|
Default value : false
|
Defined in src/angular-forms.component.ts:181
|
import { AfterViewChecked, ChangeDetectorRef, Component, EventEmitter,
Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { AngularForms, Status } from '.';
import { DataTable, Fieldset, Group, GroupType } from './group';
import { Answer, DependencyService, Question, Select, SelectService } from './question';
import { ReactiveFormsFactory } from './factory';
import { ObjectUtils, StringUtils } from './util';
@Component({
selector: 'rb-angular-forms',
template: `
<form *ngIf="Status['READY'] === status" class="rb-angular-forms" [formGroup]="formGroup" [ngClass]="{ 'read-only': readOnly }">
<ng-container *ngFor="let group of groups">
<ng-container [ngSwitch]="group.type">
<ng-container *ngSwitchCase="'group'">
<fieldset class="rb-fieldset rb-fieldset-{{ group.code }}" [formGroup]="formGroup.get(group.code)">
<legend *ngIf="'Ungrouped' !== group.description">{{ group.description }}</legend>
<ng-container *ngFor="let question of group.questions">
<ng-container [ngSwitch]="question.type">
<ng-template ngSwitchCase="checkbox">
<div class="form-group" [hidden]="hideQuestion(question, formGroup.get(group.code))">
<ng-container *ngIf="!readOnly; else readOnlyCheckbox">
<div class="checkbox">
<label>
<input type="checkbox" [name]="question.name" [formControlName]="question.name" />
<span [ngClass]="{ 'required-control': question.isRequired() }">
{{ question.description }}
</span>
</label>
<rb-validation-message [validations]="question.validations"
[control]="formGroup.get(group.code).get(question.name)"
[submitted]="submitted">
</rb-validation-message>
</div> <!--/.checkbox-->
</ng-container> <!--/!readOnly-->
<ng-template #readOnlyCheckbox>
<label>
<i class="rb-ico rb-ico-square rb-ico-{{ question.answer ? 'checked' : 'unchecked' }}" aria-hidden="true"></i>
{{ question.description }}
</label>
</ng-template> <!--/readOnly-->
</div> <!--/.form-group-->
</ng-template> <!--/checkbox-->
<ng-template ngSwitchCase="radio">
<div class="form-group" [hidden]="hideQuestion(question, formGroup.get(group.code))">
<ng-container *ngIf="!readOnly; else readOnlyRadio">
<label [ngClass]="{ 'required-control': question.isRequired() }">
{{ question.description }}
</label>
<div class="radio" *ngFor="let option of question.options">
<label>
<input type="radio" [name]="question.name" [value]="option" [formControlName]="question.name" />
{{ option }}
</label>
</div> <!--/.radio-->
<rb-validation-message [validations]="question.validations"
[control]="formGroup.get(group.code).get(question.name)"
[submitted]="submitted">
</rb-validation-message>
</ng-container> <!--/!readOnly-->
<ng-template #readOnlyRadio>
<label>{{ question.description }}</label>
<span>{{ question.answer || 'NOT_INFORMED' | translate }}</span>
</ng-template> <!--/readOnly-->
</div> <!--/.form-group-->
</ng-template> <!--/radio-->
<ng-template ngSwitchCase="select">
<div class="form-group" [hidden]="hideQuestion(question, formGroup.get(group.code))">
<ng-container *ngIf="!readOnly; else readOnlySelect">
<label [for]="question.name" [ngClass]="{ 'required-control': question.isRequired() }">
{{ question.description }}
</label>
<select [id]="question.name" class="form-control" [name]="question.name" #selectQuestion
[formControlName]="question.name"
(change)="onChangeOptionSelect(selectQuestion, formGroup.get(group.code).get(question.name), question)">
<option disabled [value]="null">
{{ question.placeholder ? question.placeholder : '' }}
</option>
<option *ngFor="let option of question.options" [value]="option['value'] || option">
{{ option['description'] || option }}
</option>
</select>
<ng-container *ngIf="question.editableOption && question.editableOption.length">
<input [hidden]="question.editableOption !== selectQuestion.value"
type="text" [id]="question.name" class="form-control editable-option" [name]="question.name"
[formControlName]="question.name" />
</ng-container>
<rb-validation-message [validations]="question.validations"
[control]="formGroup.get(group.code).get(question.name)"
[submitted]="submitted">
</rb-validation-message>
</ng-container> <!--!readOnly-->
<ng-template #readOnlySelect>
<label>{{ question.description }}</label>
<span>{{ question.answer || 'NOT_INFORMED' | translate }}</span>
</ng-template> <!--/readOnly-->
</div> <!--/.form-group-->
</ng-template> <!--/select-->
<ng-template ngSwitchCase="textarea">
<div class="form-group" [hidden]="hideQuestion(question, formGroup.get(group.code))">
<ng-container *ngIf="!readOnly; else readOnlyTextarea">
<label [for]="question.name" [ngClass]="{ 'required-control': question.isRequired() }">
{{ question.description }}
</label>
<textarea [id]="question.name" class="form-control" [name]="question.name" rows="5"
placeholder="{{ question.placeholder ? question.placeholder : '' }}"
[formControlName]="question.name">
</textarea>
<rb-validation-message [validations]="question.validations"
[control]="formGroup.get(group.code).get(question.name)"
[submitted]="submitted">
</rb-validation-message>
</ng-container> <!--!readOnly-->
<ng-template #readOnlyTextarea>
<label>{{ question.description }}</label>
<span>{{ question.answer || 'NOT_INFORMED' | translate }}</span>
</ng-template> <!--/readOnly-->
</div> <!--/.form-group-->
</ng-template> <!--/textarea-->
<ng-template ngSwitchCase="text" ngSwitchDefault>
<div class="form-group" [hidden]="hideQuestion(question, formGroup.get(group.code))">
<ng-container *ngIf="!readOnly; else readOnlyText">
<label [for]="question.name" [ngClass]="{ 'required-control': question.isRequired() }">
{{ question.description }}
</label>
<input type="text" [id]="question.name" class="form-control" [name]="question.name"
placeholder="{{ question.placeholder ? question.placeholder : '' }}"
[formControlName]="question.name" [mask]="question.mask" />
<rb-validation-message [validations]="question.validations"
[control]="formGroup.get(group.code).get(question.name)"
[submitted]="submitted">
</rb-validation-message>
</ng-container> <!--!readOnly-->
<ng-template #readOnlyText>
<label>{{ question.description }}</label>
<span>{{ question.answer || 'NOT_INFORMED' | translate }}</span>
</ng-template> <!--readOnly-->
</div> <!--/.form-group-->
</ng-template> <!--/text-->
</ng-container> <!--/ngSwitch-questionType-->
</ng-container> <!--/ngFor-question-->
</fieldset>
</ng-container> <!--/ngSwitchCase-fieldset-->
<ng-container *ngSwitchDefault>
<rb-data-table [group]="group" [formGroup]="formGroup" [formGroupSubmitted]="submitted" [readOnly]="readOnly"
(error)="onError($event)">
</rb-data-table>
</ng-container>
</ng-container> <!--/ngSwitch-groupType-->
</ng-container> <!--groups-->
</form>
`
})
export class AngularFormsComponent implements OnInit, OnChanges, AfterViewChecked {
public readonly Status: Object = Status;
public formGroup: FormGroup;
public submitted: boolean = false;
@Input() public groups: Group<any>[] = [];
@Input() public lang: string = 'en-US';
@Input() public readOnly: boolean = false;
@Output() public error: EventEmitter<Error> = new EventEmitter();
@Output() public ready: EventEmitter<boolean> = new EventEmitter();
private _originalValueFormGroup: Object;
private _status: Status;
public constructor(
private changeDetectorRef: ChangeDetectorRef,
private translateService: TranslateService
) { }
public ngOnInit(): void {
this.configTranslate();
}
public ngOnChanges(changes: SimpleChanges): void {
if (changes['groups']) {
const groups: Group<any>[] = changes['groups'].currentValue;
if (groups && groups.length) {
this._status = Status.LOADING;
this.load()
.then(() => {
this._status = Status.READY;
this.ready.emit();
})
.catch((error: Error) => {
this._status = Status.ERROR;
this.printErrorLog(error);
this.error.emit(error);
});
} else {
this.clear();
}
}
}
public ngAfterViewChecked(): void {
this.changeDetectorRef.detectChanges();
}
public getGroupByCode(code: string): Group<any> {
for (const group of this.groups) {
if (group.code === code) {
return group;
}
}
}
public hideQuestion(question: Question<any>, formGroup: FormGroup): boolean {
return DependencyService.hideQuestion(question, formGroup);
}
public onChangeOptionSelect(htmlFormControl: HTMLInputElement, formControl: FormControl, question: Select): void {
SelectService.onChangeOption(htmlFormControl, formControl, question);
}
public submit(): void {
this.submitted = true;
}
public getForm(): { valid: boolean, value: Object } {
return { valid: this.isValid(), value: this.getAnswersGroups() };
}
public isPristine(): boolean {
return ObjectUtils.isEquals(this._originalValueFormGroup, this.formGroup.value);
}
public isDirty(): boolean {
return !ObjectUtils.isEquals(this._originalValueFormGroup, this.formGroup.value);
}
public isValid(): boolean {
return this.formGroup.valid;
}
public getAnswersGroups(): Object {
const answersGroups: Object = ObjectUtils.clone(this.formGroup.value);
Object.keys(answersGroups).forEach((groupIndex: string) => {
if (answersGroups[groupIndex] instanceof Array) {
(<Array<Object>>answersGroups[groupIndex]).map((answersGroup: Object, index: number) =>
this.convertAnswersDataTable(answersGroup, <DataTable>this.getGroupByCode(groupIndex), index + 1));
return;
}
answersGroups[groupIndex] = this.convertAnswersFieldset(answersGroups[groupIndex], <Fieldset>this.getGroupByCode(groupIndex));
});
return answersGroups;
}
public getAnswers(): Object {
const answersGroups: Object = this.getAnswersGroups();
const answers: Object = {};
Object.keys(answersGroups).forEach((groupIndex: string) => {
if (answersGroups[groupIndex] instanceof Array) {
answers[groupIndex] = answersGroups[groupIndex];
return;
}
Object.keys(answersGroups[groupIndex])
.forEach((questionIndex: string) => answers[questionIndex] = answersGroups[groupIndex][questionIndex]);
});
return answers;
}
public onError(error: Error): void {
this.clear();
this.printErrorLog(error);
this.error.emit(error);
}
public get originalValueFormGroup(): Object {
return this._originalValueFormGroup;
}
public get status(): Status {
return this._status;
}
private configTranslate(): void {
this.translateService.addLangs(['en-US', 'pt-BR']);
this.translateService.setDefaultLang('en-US');
this.translateService.use(this.lang || 'en-US');
}
private async load(): Promise<void> {
return new Promise<void>(async (resolve: () => void, reject: (error: Error) => void) => {
try {
this.groups = await AngularForms.fromJson(this.groups);
this.formGroup = await ReactiveFormsFactory.createFormGroupFromGroups(this.groups);
setTimeout(() => this.initOriginalValueFormGroup(), 2000);
resolve();
} catch (error) {
reject(error);
}
});
}
private initOriginalValueFormGroup(): void {
this._originalValueFormGroup = ObjectUtils.clone(this.formGroup.value);
}
private convertAnswersFieldset(answersGroup: Object, group: Fieldset): Object {
Object.keys(answersGroup).forEach((questionName: string) => {
const question: Question<any> = group.getQuestionByName(questionName);
const id: number | string = (<Answer<any>>question.answer).id || null;
const value: string = StringUtils.convertToString(answersGroup[questionName]);
answersGroup[questionName] = new Answer(value, id);
});
return answersGroup;
}
private convertAnswersDataTable(answersGroup: Object, group: DataTable, index: number): Object {
Object.keys(answersGroup).forEach((questionName: string) => {
const question: Question<any> = group.getQuestionByNameAndIndex(questionName, index);
const id: number | string = question ? (<Answer<any>>question.answer).id : null;
const value: string = StringUtils.convertToString(answersGroup[questionName]);
answersGroup[questionName] = new Answer(value, id);
});
return answersGroup;
}
private clear(): void {
this._status = null;
this.formGroup = null;
}
private printErrorLog(error: Error): void {
console.error(`[AngularForms] ${error.name} :: ${error.message}`);
}
}