Skip to content

Commit

Permalink
fix(form): template
Browse files Browse the repository at this point in the history
add translate pipe to save button
add ng-content ajfFormTopToolbarButtons for adding buttons on top toolbar
now you can override the save form button
added form 2e2 specs
fix aria label form single choice fields and input fields
  • Loading branch information
peppedeka authored and trik committed Mar 2, 2021
1 parent a4f7ccf commit da4f4df
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/dev-app/mat-forms/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ng_module(
deps = [
"//src/material/forms",
"@npm//@angular/router",
"@npm//rxjs",
],
)

Expand Down
6 changes: 4 additions & 2 deletions src/dev-app/mat-forms/forms-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ <h5>Context</h5>
</div>
</mat-grid-tile>
</mat-grid-list>
<div class="demo-form-container">
<ajf-form [form]="form" [hasStartMessage]="false" [hasEndMessage]="false" hideTopToolbar [readonly]="readonly"></ajf-form>
<div class="demo-form-container" *ngIf="form$|async as form">
<ajf-form [form]="form" [hasStartMessage]="false" [hasEndMessage]="false" [readonly]="readonly">
<button ajfFormTopToolbarButtons mat-button default>button added by form demo</button>
</ajf-form>
</div>
</section>
</div>
14 changes: 9 additions & 5 deletions src/dev-app/mat-forms/forms-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
import {AjfContext} from '@ajf/core/models';
import {AjfFieldService} from '@ajf/material/forms';
import {Component} from '@angular/core';
import {BehaviorSubject} from 'rxjs';

import {CustomSelectMultiple} from './custom-select-multiple';
import {formContext, formSchema} from './form';
Expand All @@ -42,7 +43,8 @@ import {formContext, formSchema} from './form';
})
export class FormsDemo {
formSchema: string = JSON.stringify(formSchema);
form: AjfForm;
form$: BehaviorSubject<AjfForm|null> = new BehaviorSubject<AjfForm|null>(null);

context: string = JSON.stringify(formContext);

get readonly() {
Expand All @@ -64,8 +66,9 @@ export class FormsDemo {
createInstance: createFieldWithChoicesInstance as any,
isFieldWithChoice: true,
});
this.form = AjfFormSerializer.fromJson(formSchema, formContext);
console.log(this.form);
const form = AjfFormSerializer.fromJson(formSchema, formContext);
this.form$.next(form);
console.log(form);
}

setSchema(): void {
Expand All @@ -81,8 +84,9 @@ export class FormsDemo {
} else {
context = {};
}
this.form = AjfFormSerializer.fromJson(schema, context);
console.log(this.form);
const form = AjfFormSerializer.fromJson(schema, context);
console.log(form);
this.form$.next(form);
} catch (e) {
console.log(e);
}
Expand Down
8 changes: 6 additions & 2 deletions src/e2e-app/mat-form/mat-form-e2e.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<h1>Number Field Example</h1>
<section>
<ajf-form [form]="form"></ajf-form>
</section>
<ajf-form
[form]="form"
[topBar]="(topBar$|async)|| false"
[hideTopToolbar]="(hideToolbar$|async)|| false"
></ajf-form>
</section>
2 changes: 2 additions & 0 deletions src/e2e-app/mat-form/mat-form-e2e.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@

import {AjfFormsModule as CoreFormsModule} from '@ajf/core/forms';
import {AjfFormsModule} from '@ajf/material/forms';
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';

import {MaterialFormE2E} from './mat-form-e2e';

@NgModule({
imports: [
AjfFormsModule,
CommonModule,
CoreFormsModule,
],
declarations: [
Expand Down
33 changes: 30 additions & 3 deletions src/e2e-app/mat-form/mat-form-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
*/

import {AjfForm, AjfFormSerializer} from '@ajf/core/forms';
import {Component} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';
import {Observable, of} from 'rxjs';
import {filter, startWith, switchMap} from 'rxjs/operators';

const formSchema: any = {
choicesOrigins: [{
Expand Down Expand Up @@ -65,11 +68,35 @@ const formSchema: any = {
selector: 'mat-form-e2e',
templateUrl: 'mat-form-e2e.html',
})
export class MaterialFormE2E {
export class MaterialFormE2E implements OnInit {
formSchema: string = JSON.stringify(formSchema);
form: AjfForm;
routeStream$: Observable<Params> = this._route.queryParams;
topBar$: Observable<boolean> = this.routeStream$.pipe(
filter(p => p != null), switchMap((params) => {
let res = false;
if (params.topbar != null && params.topbar === 'true') {
res = true;
}
return of(res);
}),
startWith(false));

constructor() {
hideToolbar$: Observable<boolean> = this.routeStream$.pipe(
filter(p => p != null), switchMap((params) => {
let res = false;
if (params.hidetoolbar != null && params.hidetoolbar === 'true') {
res = true;
}
return of(res);
}),
startWith(false));

constructor(private _route: ActivatedRoute) {}
ngOnInit(): void {
this.form = AjfFormSerializer.fromJson(formSchema);
this._route.queryParams.subscribe(params => {
console.log(params);
});
}
}
8 changes: 7 additions & 1 deletion src/ionic/forms/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
<ion-toolbar *ngIf="!hideTopToolbar">
{{ title | translate }}
<ion-buttons slot="end">
<ion-button *ngIf="!saveDisabled" (click)="onSave($event)">{{ 'Save' | translate }}</ion-button>
<!-- this content projection allow to add buttons on toolbar-->
<ng-content select="[ajfFormTopToolbarButtons]"></ng-content>
<!-- apply a default save button only when ajfFormSaveButton is empty-->
<span *ngIf="!saveDisabled" (click)="onSave($event)">
<span #saveButton><ng-content select="[ajfFormSaveButton]"></ng-content></span>
<ion-button *ngIf="saveButton != null && saveButton.childNodes != null && saveButton.childNodes.length == 0">{{ 'Save' | translate }}</ion-button>
</span>
</ion-buttons>
</ion-toolbar>
<div class="ajf-slider-container">
Expand Down
89 changes: 89 additions & 0 deletions src/material/forms/form.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {browser, by, element} from 'protractor';

describe('ajf-form test top toolbar input', () => {
it(`topbar input is true and hideTopToolbar is not defined:
should show three mat toolbars(topBar buttonsBar pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?topbar=true');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(3);

const topBar = toolbars[0];
expect(await topBar.getText()).toBe('Number Field Example');
const buttonsBar = toolbars[1];
expect(await buttonsBar.getText()).toBe('Save');
});
it(`topbar input is true and hideTopToolbar is false:
should show one mat toolbar(pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?topbar=true&hidetoolbar=false');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(3);

const topBar = toolbars[0];
expect(await topBar.getText()).toBe('Number Field Example');
const buttonsBar = toolbars[1];
expect(await buttonsBar.getText()).toBe('Save');
});
it(`topbar input is true and hideTopToolbar is true:
should show one mat toolbar(pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?topbar=true&hidetoolbar=true');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(1);
});
it(`topbar input is false and hideTopToolbar is not defined:
should show two mat toolbars(buttonsBar pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?topbar=false');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(2);

const buttonsBar = toolbars[0];
expect(await buttonsBar.getText()).toBe('Save');
});
it(`topbar input is false and hideTopToolbar is false:
should show two mat toolbars(buttonsBar pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?topbar=false&hidetoolbar=false');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(2);

const buttonsBar = toolbars[0];
expect(await buttonsBar.getText()).toBe('Save');
});
it(`topbar input is false and hideTopToolbar is true:
should show one mat toolbar(pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?topbar=true&hidetoolbar=true');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(1);
});
it(`topbar input is not defined and hideTopToolbar is not defined:
should show two mat toolbars(buttonsBar pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(2);

const buttonsBar = toolbars[0];
expect(await buttonsBar.getText()).toBe('Save');
});
it(`topbar input is not defined and hideTopToolbar is false:
should show two mat toolbars(buttonsBar pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?hidetoolbar=false');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(2);

const buttonsBar = toolbars[0];
expect(await buttonsBar.getText()).toBe('Save');
});
it(`topbar input is not defined and hideTopToolbar is true:
should show one mat toolbar(pageSliderToolBar)`,
async () => {
await browser.get('/mat-form/?hidetoolbar=true');
const toolbars = await element.all(by.tagName('mat-toolbar')).getWebElements();
expect(toolbars.length).toBe(1);
});
});
18 changes: 11 additions & 7 deletions src/material/forms/form.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
<ng-container *ngIf="formGroup|async as fg">
<form novalidate [formGroup]="fg!">
<div class="ajf-form-container">

<mat-toolbar *ngIf="!hideTopToolbar" class="ajf-btn-strip">
<mat-toolbar *ngIf="!hideTopToolbar && topBar" class="ajf-btn-strip">
<ng-template ngFor let-slideInstance [ngForOf]="slides|async" [ngForTrackBy]="trackNodeById">
<button mat-button class="ajf-topbar-button"
*ngIf="topBar != null && slideInstance.node != null && slideInstance.node.label != null && slideInstance.node.label.length > 0"
*ngIf="slideInstance.node != null && slideInstance.node.label != null && slideInstance.node.label.length > 0"
(click)="scrollToSlide(slideInstance)">{{slideInstance.node.label | translate}}</button>
</ng-template>
</mat-toolbar>

<mat-toolbar *ngIf="!hideTopToolbar">
{{ title }}
<span class="ajf-spacer"></span>
<button mat-button default *ngIf="!saveDisabled" (click)="onSave($event)" translate>Save</button>
<!-- this content projection allow to add buttons on toolbar -->
<ng-content select="[ajfFormTopToolbarButtons]"></ng-content>
<!-- apply a default save button only when ajfFormSaveButton is empty -->
<span *ngIf="!saveDisabled" (click)="onSave($event)">
<span #saveButton><ng-content select="[ajfFormSaveButton]"></ng-content></span>
<button *ngIf="saveButton != null && saveButton.childNodes != null && saveButton.childNodes.length == 0" mat-button default>{{'Save'|translate}}</button>
</span>
</mat-toolbar>
<div class="ajf-slider-container">
<ajf-page-slider (orientationChange)="orientationChangeHandler($event)" [fixedOrientation]="fixedOrientation"
Expand Down Expand Up @@ -68,7 +72,7 @@ <h2>
<i [class]="(fieldInstance|ajfAsFieldInstance).node.fieldType | ajfFieldIcon"
item-right></i>
<p>{{ ((fieldInstance|ajfAsFieldInstance).node.description || '') | translate }}</p>
<label *ngIf="(fieldInstance|ajfAsFieldInstance).node.fieldType !== 7"
<label [attr.id]="fieldInstance.node.name" *ngIf="(fieldInstance|ajfAsFieldInstance).node.fieldType !== 7"
[innerHTML]="fieldInstance.node.label | translate"></label>
<mat-icon class="ajf-tooltip-icon"
*ngIf="(fieldInstance|ajfAsFieldInstance).node?.hint as hint" [matTooltip]="hint"
Expand Down Expand Up @@ -118,7 +122,7 @@ <h2>
<i [class]="(fieldInstance|ajfAsFieldInstance).node.fieldType | ajfFieldIcon"
item-right></i>
<p>{{ ((fieldInstance|ajfAsFieldInstance).node.description || '') | translate }}</p>
<label [innerHTML]="fieldInstance.node.label | translate"></label>
<label [attr.id]="fieldInstance.node.name" [innerHTML]="fieldInstance.node.label | translate"></label>
<mat-icon class="ajf-tooltip-icon"
*ngIf="(fieldInstance|ajfAsFieldInstance).node?.hint as hint" [matTooltip]="hint"
matTooltipPosition="right">
Expand Down
4 changes: 2 additions & 2 deletions src/material/forms/input-field.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<mat-form-field *ngIf="control|async as ctrl">
<input matInput *ngIf="type === 'text'" type="text" [formControl]="ctrl!"
[readonly]="instance|ajfIsReadonlyInputField">
[readonly]="instance|ajfIsReadonlyInputField" [attr.aria-labelledby]="instance.node.name">
<input matInput *ngIf="type === 'number'" type="number" [formControl]="ctrl!"
[readonly]="instance|ajfIsReadonlyInputField">
[readonly]="instance|ajfIsReadonlyInputField" [attr.aria-labelledby]="instance.node.name">
</mat-form-field>
1 change: 1 addition & 0 deletions src/material/forms/single-choice-field.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
</ng-container>
<ng-template #expanded>
<mat-radio-group *ngIf="control|async as ctrl" class="ajf-choices-container"
[attr.aria-labelledby]="instance.node.name"
[formControl]="ctrl!">
<mat-radio-button [value]="choice.value"
*ngFor="let choice of instance.filteredChoices">
Expand Down
2 changes: 1 addition & 1 deletion tools/public_api_guard/ionic/forms.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export declare class AjfFormRenderer extends AjfCoreFormRenderer implements Afte
static ngAcceptInputType_hideTopToolbar: BooleanInput;
static ngAcceptInputType_readonly: BooleanInput;
static ngAcceptInputType_saveDisabled: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<AjfFormRenderer, "ajf-form", never, {}, {}, never, ["[ajfFormStartMessageTitle]", "[ajfFormStartMessage]", "[ajfFormEndMessageTitle]", "[ajfFormEndMessage]"]>;
static ɵcmp: i0.ɵɵComponentDefWithMeta<AjfFormRenderer, "ajf-form", never, {}, {}, never, ["[ajfFormTopToolbarButtons]", "[ajfFormSaveButton]", "[ajfFormStartMessageTitle]", "[ajfFormStartMessage]", "[ajfFormEndMessageTitle]", "[ajfFormEndMessage]"]>;
static ɵfac: i0.ɵɵFactoryDef<AjfFormRenderer, never>;
}

Expand Down
2 changes: 1 addition & 1 deletion tools/public_api_guard/material/forms.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export declare class AjfFormRenderer extends AjfCoreFormRenderer {
static ngAcceptInputType_hideTopToolbar: BooleanInput;
static ngAcceptInputType_readonly: BooleanInput;
static ngAcceptInputType_saveDisabled: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<AjfFormRenderer, "ajf-form", never, { "topBar": "topBar"; }, {}, never, ["[ajfFormStartMessageTitle]", "[ajfFormStartMessage]", "[ajfFormEndMessageTitle]", "[ajfFormEndMessage]"]>;
static ɵcmp: i0.ɵɵComponentDefWithMeta<AjfFormRenderer, "ajf-form", never, { "topBar": "topBar"; }, {}, never, ["[ajfFormTopToolbarButtons]", "[ajfFormSaveButton]", "[ajfFormStartMessageTitle]", "[ajfFormStartMessage]", "[ajfFormEndMessageTitle]", "[ajfFormEndMessage]"]>;
static ɵfac: i0.ɵɵFactoryDef<AjfFormRenderer, never>;
}

Expand Down

0 comments on commit da4f4df

Please sign in to comment.