Skip to content

Commit

Permalink
fix: (Platform) Add ability to use fdp-form-field out of fdp-form-gro…
Browse files Browse the repository at this point in the history
…up-content (#5127)

* add formGroupContainer input
  • Loading branch information
dimamarksman committed Apr 14, 2021
1 parent c25b81a commit 3b384ce
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 19 deletions.
Expand Up @@ -23,7 +23,6 @@ import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coerci
import { Subject } from 'rxjs';
import { startWith, takeUntil } from 'rxjs/operators';


import { FormFieldControl } from '../../form-control';
import { FormField } from '../../form-field';
import { Column, LabelLayout, HintPlacement } from '../../form-options';
Expand Down Expand Up @@ -127,6 +126,13 @@ export class FormFieldComponent implements FormField, AfterContentInit, AfterVie
@Input()
disabled = false;

/**
* Form Group Container to bind the Form-Field to.
* This will override default value injected by constructor
*/
@Input()
formGroupContainer: FormGroupContainer;

@Output()
onChange: EventEmitter<string> = new EventEmitter<string>();

Expand Down Expand Up @@ -155,12 +161,18 @@ export class FormFieldComponent implements FormField, AfterContentInit, AfterVie
/** @hidden */
constructor(
private _cd: ChangeDetectorRef,
private _elementRef: ElementRef,
@Optional() readonly formGroupContainer: FormGroupContainer,
@Optional() @SkipSelf() @Host() readonly formFieldGroup: FormFieldGroup) {
@Optional() formGroupContainer: FormGroupContainer,
@Optional() @SkipSelf() @Host() readonly formFieldGroup: FormFieldGroup
) {
// provides capability to make a field disabled. useful in reactive form approach.
this.formControl = new FormControl({ value: null, disabled: this.disabled });

// formGroupContainer can be injected only if current form-field is located
// insight formGroupContainer content.
// If this is not the case the formGroupContainer
// will be undefined (known angular issue),
// in such case formGroupContainer can be pointed explicitly using
// component input annotation
this.formGroupContainer = formGroupContainer;
}

/** @hidden */
Expand Down
116 changes: 102 additions & 14 deletions libs/platform/src/lib/components/form/form.spec.ts
Expand Up @@ -2,8 +2,8 @@ import { Component, ViewChild, ElementRef } from '@angular/core';
import { TestBed, ComponentFixture, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ReactiveFormsModule, FormGroup } from '@angular/forms';
import { FormGroupComponent } from '@fundamental-ngx/platform';

import { FormGroupComponent } from './form-group/form-group.component';
import { FdpFormGroupModule } from './form-group/fdp-form.module';
import { PlatformInputModule } from './input/fdp-input.module';
import { FormFieldComponent } from './form-group/form-field/form-field.component';
Expand Down Expand Up @@ -93,12 +93,14 @@ describe('Simple Form', () => {
let fixture: ComponentFixture<SimpleFormTestComponent>;
let host: SimpleFormTestComponent;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, FdpFormGroupModule, PlatformInputModule],
declarations: [SimpleFormTestComponent]
}).compileComponents();
}));
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, FdpFormGroupModule, PlatformInputModule],
declarations: [SimpleFormTestComponent]
}).compileComponents();
})
);

beforeEach(() => {
fixture = TestBed.createComponent(SimpleFormTestComponent);
Expand All @@ -117,7 +119,8 @@ describe('Simple Form', () => {

it('should highlight the required fields', () => {
const labels: ElementRef<HTMLElement>[] = fixture.debugElement.queryAll(By.css('label'));
const getFormLabelElement = (label: ElementRef<HTMLElement>) => fixture.debugElement.query(By.css('span')).nativeElement;
const getFormLabelElement = (label: ElementRef<HTMLElement>) =>
fixture.debugElement.query(By.css('span')).nativeElement;
expect(labels.length).toBe(3);
expect(getFormLabelElement(labels[0]).classList.contains('fd-form-label--required')).toBeTruthy();
expect(getFormLabelElement(labels[1]).classList.contains('fd-form-label--required')).toBeTruthy();
Expand Down Expand Up @@ -229,12 +232,14 @@ describe('Nested Form Groups', () => {
let fixture: ComponentFixture<NestedFormGroupsTestComponent>;
let host: NestedFormGroupsTestComponent;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, FdpFormGroupModule, PlatformInputModule],
declarations: [NestedFormGroupsTestComponent]
}).compileComponents();
}));
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, FdpFormGroupModule, PlatformInputModule],
declarations: [NestedFormGroupsTestComponent]
}).compileComponents();
})
);

beforeEach(() => {
fixture = TestBed.createComponent(NestedFormGroupsTestComponent);
Expand Down Expand Up @@ -284,3 +289,86 @@ describe('Nested Form Groups', () => {
});
});
});

describe('fdp-form-field out of fdp-form-group', () => {
@Component({
template: `
<form [formGroup]="userFormGroup" (ngSubmit)="onSubmit()">
<fdp-form-group
#fdpUserFormGroup
[object]="user"
[formGroup]="userFormGroup"
[hintPlacement]="'right'"
[i18Strings]="i18n"
>
<ng-container
*ngTemplateOutlet="formFieldTemplateRef; context: { fdpFormGroup: fdpUserFormGroup }"
></ng-container>
<ng-template #i18n let-errors>
<span *ngIf="errors && errors.required" class="error">This field is required.</span>
</ng-template>
</fdp-form-group>
</form>
<ng-template #formFieldTemplateRef let-fdpFormGroup="fdpFormGroup">
<fdp-form-field
#formFieldFirstName
id="firstName"
label="First Name"
required="true"
[formGroupContainer]="fdpFormGroup"
>
<fdp-input name="firstName" [formControl]="formFieldFirstName.formControl"></fdp-input>
</fdp-form-field>
</ng-template>
`
})
class HostFormComponent {
@ViewChild('fdpUserFormGroup') fdpFormGroupUser: FormGroupComponent;
@ViewChild('formFieldFirstName') fdpFormFieldFirstName: FormFieldComponent;

public userFormGroup: FormGroup = new FormGroup({});

public user = {
firstName: 'Tom'
};

public result: any = null;

onSubmit(): void {
this.result = this.userFormGroup.value;
}
}

let fixture: ComponentFixture<HostFormComponent>;
let host: HostFormComponent;

beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, FdpFormGroupModule, PlatformInputModule],
declarations: [HostFormComponent],
}).compileComponents();
})
);

beforeEach(() => {
fixture = TestBed.createComponent(HostFormComponent);
host = fixture.componentInstance;

fixture.detectChanges();
});

it('should be created', () => {
expect(host).toBeDefined();
});

it('should link formField to given formGroup through [formGroupContainer] input', () => {
const fdpFormGroup: FormGroupComponent = host.fdpFormGroupUser;
const fdpFormField: FormFieldComponent = host.fdpFormFieldFirstName;

expect(fdpFormGroup).toBeDefined();
expect(fdpFormField).toBeDefined();
expect(fdpFormField.formGroupContainer).toBe(fdpFormGroup);
});
});

0 comments on commit 3b384ce

Please sign in to comment.