From ee56a1faa630f34a85f14faa2640a8db2875706a Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Tue, 15 Nov 2016 15:13:05 +0000 Subject: [PATCH] #967 rework container model structure - now FormFieldModel provides information about columns and child fields - greatly simplified models - visibility engine fixes --- .../form-field/form-field.component.ts | 20 +++--- .../container/container-column.model.spec.ts | 2 +- .../widgets/container/container.widget.html | 3 +- .../container/container.widget.model.spec.ts | 61 ++++++------------- .../container/container.widget.model.ts | 48 ++------------- .../container/container.widget.spec.ts | 20 +++--- .../widgets/container/container.widget.ts | 2 +- .../container-column.model.ts | 2 +- .../widgets/core/container.model.spec.ts | 9 +-- .../widgets/core/container.model.ts | 11 ++-- .../widgets/core/form-field.model.ts | 32 +++++++++- .../src/components/widgets/core/form.model.ts | 6 +- .../components/widgets/core/tab.model.spec.ts | 2 +- .../components/widgets/text/text.widget.html | 2 +- .../components/widgets/widget.component.ts | 1 + .../widget-visibility.service.spec.ts | 8 +-- .../src/services/widget-visibility.service.ts | 3 +- 17 files changed, 97 insertions(+), 135 deletions(-) rename ng2-components/ng2-activiti-form/src/components/widgets/{container => core}/container-column.model.ts (92%) diff --git a/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts b/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts index 07d6f2899c..5dde745ead 100644 --- a/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts +++ b/ng2-components/ng2-activiti-form/src/components/form-field/form-field.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, OnInit, ViewChild, ViewContainerRef, Input, ComponentRef, ComponentFactoryResolver, Output, EventEmitter/*, Injector*/ } from '@angular/core'; +import { Component, OnInit, ViewChild, ViewContainerRef, Input, ComponentRef, ComponentFactoryResolver/*,Output, EventEmitter, Injector*/ } from '@angular/core'; import { WidgetVisibilityService } from './../../services/widget-visibility.service'; import { FormRenderingService } from './../../services/form-rendering.service'; import { WidgetComponent } from './../widgets/widget.component'; @@ -23,7 +23,11 @@ import { FormFieldModel/*, FormWidgetModel*/ } from './../widgets/core/index'; @Component({ selector: 'form-field', - template: `
` + template: ` +
+
+
+ ` }) export class FormFieldComponent implements OnInit { @@ -33,10 +37,6 @@ export class FormFieldComponent implements OnInit { @Input() field: FormFieldModel = null; - /** @deprecated component handles visibilty itself */ - @Output() - fieldChanged: EventEmitter = new EventEmitter(); - private componentRef: ComponentRef<{}>; constructor( @@ -54,12 +54,10 @@ export class FormFieldComponent implements OnInit { this.componentRef = this.container.createComponent(factory/*, 0, this.injector*/); let instance = this.componentRef.instance; instance.field = this.field; - instance.fieldChanged.subscribe(args => { - if (this.field && this.field.form) { - this.visibilityService.refreshVisibility(this.field.form); + instance.fieldChanged.subscribe(field => { + if (field && field.form) { + this.visibilityService.refreshVisibility(field.form); } - /** @deprecated */ - this.fieldChanged.emit(args); }); } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts index beef5ba952..b37516b346 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { ContainerColumnModel } from './container-column.model'; +import { ContainerColumnModel } from './../core/container-column.model'; import { FormModel } from './../core/form.model'; import { FormFieldModel } from './../core/form-field.model'; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html index c0976a6de9..987e2803e6 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.html @@ -1,3 +1,4 @@ +
{{content?.isVisible}}

- +

diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts index a1cb578dd1..4aedb5ce9f 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.spec.ts @@ -17,52 +17,26 @@ import { ContainerWidgetModel } from './container.widget.model'; import { FormModel } from './../core/form.model'; +import { FormFieldModel } from './../core/form-field.model'; import { FormFieldTypes } from './../core/form-field-types'; describe('ContainerWidgetModel', () => { it('should store the form reference', () => { let form = new FormModel(); - let model = new ContainerWidgetModel(form); + let field = new FormFieldModel(form); + let model = new ContainerWidgetModel(field); expect(model.form).toBe(form); }); - it('should store original json', () => { - let json = {}; - let model = new ContainerWidgetModel(null, json); - expect(model.json).toBe(json); - }); - - it('should have 1 column layout by default', () => { - let container = new ContainerWidgetModel(null, null); - expect(container.numberOfColumns).toBe(1); - }); - it('should be expanded by default', () => { - let container = new ContainerWidgetModel(null, null); + let container = new ContainerWidgetModel(null); expect(container.isExpanded).toBeTruthy(); }); - /* - it('should setup with json config', () => { - let json = { - fieldType: '', - id: '', - name: '', - type: '', - tab: '', - numberOfColumns: 2, - params: {} - }; - let container = new ContainerWidgetModel(null, json); - Object.keys(json).forEach(key => { - expect(container[key]).toEqual(json[key]); - }); - }); - */ - it('should wrap fields into columns on setup', () => { let form = new FormModel(); + let json = { fieldType: '', id: '', @@ -83,7 +57,10 @@ describe('ContainerWidgetModel', () => { '3': null } }; - let container = new ContainerWidgetModel(form, json); + + let field = new FormFieldModel(form, json); + + let container = new ContainerWidgetModel(field); expect(container.columns.length).toBe(3); let col1 = container.columns[0]; @@ -100,47 +77,47 @@ describe('ContainerWidgetModel', () => { }); it('should allow collapsing only when of a group type', () => { - let container = new ContainerWidgetModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.CONTAINER, params: { allowCollapse: true } - }); + })); expect(container.isCollapsible()).toBeFalsy(); - container = new ContainerWidgetModel(new FormModel(), { + container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true } - }); + })); expect(container.isCollapsible()).toBeTruthy(); }); it('should allow collapsing only when explicitly defined in params', () => { - let container = new ContainerWidgetModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: {} - }); + })); expect(container.isCollapsible()).toBeFalsy(); - container = new ContainerWidgetModel(new FormModel(), { + container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true } - }); + })); expect(container.isCollapsible()).toBeTruthy(); }); it('should be collapsed by default', () => { - let container = new ContainerWidgetModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true, collapseByDefault: true } - }); + })); expect(container.isCollapsedByDefault()).toBeTruthy(); }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts index bd57023af9..d9c338f38a 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.model.ts @@ -16,14 +16,12 @@ */ import { ContainerModel } from './../core/container.model'; -import { FormModel } from './../core/form.model'; -import { ContainerColumnModel } from './container-column.model'; +import { ContainerColumnModel } from './../core/container-column.model'; import { FormFieldTypes } from './../core/form-field-types'; import { FormFieldModel } from './../core/form-field.model'; export class ContainerWidgetModel extends ContainerModel { - numberOfColumns: number = 1; columns: ContainerColumnModel[] = []; isExpanded: boolean = true; @@ -51,48 +49,12 @@ export class ContainerWidgetModel extends ContainerModel { return collapseByDefault; } - constructor(form: FormModel, json?: any) { - super(form, json); - - if (json) { - this.numberOfColumns = json.numberOfColumns; - - let columnSize: number = 12; - if (this.numberOfColumns > 1) { - columnSize = 12 / this.numberOfColumns; - } - - for (let i = 0; i < this.numberOfColumns; i++) { - let col = new ContainerColumnModel(); - col.size = columnSize; - this.columns.push(col); - } - - if (json.fields) { - Object.keys(json.fields).map(key => { - let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f)); - let col = this.columns[parseInt(key, 10) - 1]; - col.fields = fields; - }); - } + constructor(field: FormFieldModel) { + super(field); + if (this.field) { + this.columns = this.field.columns || []; this.isExpanded = !this.isCollapsedByDefault(); - this.children = this.getFormFields(); } } - - private getFormFields(): FormFieldModel[] { - let result: FormFieldModel[] = []; - - for (let j = 0; j < this.columns.length; j++) { - let column = this.columns[j]; - for (let k = 0; k < column.fields.length; k++) { - let field = column.fields[k]; - result.push(field); - } - } - - return result; - } - } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts index 151edc98b1..f8da8f8d0f 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.spec.ts @@ -53,12 +53,12 @@ describe('ContainerWidget', () => { }); it('should toggle underlying group container', () => { - let container = new ContainerWidgetModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true } - }); + })); let widget = new ContainerWidget(); widget.content = container; @@ -71,9 +71,9 @@ describe('ContainerWidget', () => { }); it('should toggle only collapsible container', () => { - let container = new ContainerWidgetModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP - }); + })); let widget = new ContainerWidget(); widget.content = container; @@ -84,12 +84,12 @@ describe('ContainerWidget', () => { }); it('should toggle only group container', () => { - let container = new ContainerWidgetModel(new FormModel(), { + let container = new ContainerWidgetModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.CONTAINER, params: { allowCollapse: true } - }); + })); let widget = new ContainerWidget(); widget.content = container; @@ -134,18 +134,18 @@ describe('ContainerWidget', () => { beforeEach(() => { componentHandler = jasmine.createSpyObj('componentHandler', ['upgradeAllRegistered', 'upgradeElement']); window['componentHandler'] = componentHandler; - fakeContainerVisible = new ContainerWidgetModel(new FormModel(fakeFormJson), { + fakeContainerVisible = new ContainerWidgetModel(new FormFieldModel(new FormModel(fakeFormJson), { fieldType: FormFieldTypes.GROUP, id: 'fake-cont-id-1', name: 'fake-cont-1-name', type: FormFieldTypes.GROUP - }); - fakeContainerInvisible = new ContainerWidgetModel(new FormModel(fakeFormJson), { + })); + fakeContainerInvisible = new ContainerWidgetModel(new FormFieldModel(new FormModel(fakeFormJson), { fieldType: FormFieldTypes.GROUP, id: 'fake-cont-id-2', name: 'fake-cont-2-name', type: FormFieldTypes.GROUP - }); + })); fakeContainerVisible.field.isVisible = true; fakeContainerInvisible.field.isVisible = false; }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts index f5bde61620..4c6c24784b 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/container/container.widget.ts @@ -37,7 +37,7 @@ export class ContainerWidget extends WidgetComponent implements OnInit, AfterVie ngOnInit() { if (this.field) { - this.content = new ContainerWidgetModel(this.field.form, this.field.json); + this.content = new ContainerWidgetModel(this.field); } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts similarity index 92% rename from ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.ts rename to ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts index cbad0a523c..94216ed655 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/container/container-column.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container-column.model.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { FormFieldModel } from './../core/form-field.model'; +import { FormFieldModel } from './form-field.model'; export class ContainerColumnModel { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts index 5c5b2447d2..893b4e0517 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.spec.ts @@ -17,19 +17,14 @@ import { ContainerModel } from './container.model'; import { FormModel } from './form.model'; +import { FormFieldModel } from './form-field.model'; describe('ContainerModel', () => { it('should store the form reference', () => { let form = new FormModel(); - let model = new ContainerModel(form); + let model = new ContainerModel(new FormFieldModel(form)); expect(model.form).toBe(form); }); - it('should store original json', () => { - let json = {}; - let model = new ContainerModel(null, json); - expect(model.json).toBe(json); - }); - }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts index a4e96116f4..c9e6c092c0 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/container.model.ts @@ -16,23 +16,20 @@ */ import { FormWidgetModel } from './form-widget.model'; -import { FormModel } from './form.model'; import { FormFieldModel } from './form-field.model'; export class ContainerModel extends FormWidgetModel { field: FormFieldModel; - children: FormFieldModel[] = []; get isVisible(): boolean { return this.field.isVisible; } - constructor(form: FormModel, json?: any) { - super(form, json); - - if (json) { - this.field = new FormFieldModel(form, json); + constructor(field: FormFieldModel) { + if (field) { + super(field.form, field.json); + this.field = field; } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts index a77a985dc4..693f865867 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form-field.model.ts @@ -20,6 +20,7 @@ import { FormFieldOption } from './form-field-option'; import { FormFieldTypes } from './form-field-types'; import { FormFieldMetadata } from './form-field-metadata'; import { FormModel } from './form.model'; +import { ContainerColumnModel } from './container-column.model'; import { WidgetVisibilityModel } from '../../../models/widget-visibility.model'; import { FormFieldValidator, @@ -74,7 +75,12 @@ export class FormFieldModel extends FormWidgetModel { enableFractions: boolean = false; currency: string = null; - // advanced members + // container model members + numberOfColumns: number = 1; + fields: FormFieldModel[] = []; + columns: ContainerColumnModel[] = []; + + // util members emptyOption: FormFieldOption; validationSummary: string; validators: FormFieldValidator[] = []; @@ -150,6 +156,30 @@ export class FormFieldModel extends FormWidgetModel { this.enableFractions = json.enableFractions; this.currency = json.currency; this._value = this.parseValue(json); + + // + this.numberOfColumns = json.numberOfColumns; + + let columnSize: number = 12; + if (this.numberOfColumns > 1) { + columnSize = 12 / this.numberOfColumns; + } + + for (let i = 0; i < this.numberOfColumns; i++) { + let col = new ContainerColumnModel(); + col.size = columnSize; + this.columns.push(col); + } + + if (json.fields) { + Object.keys(json.fields).map(key => { + let fields = (json.fields[key] || []).map(f => new FormFieldModel(form, f)); + let col = this.columns[parseInt(key, 10) - 1]; + col.fields = fields; + this.fields.push(...fields); + }); + } + // } if (this.hasEmptyValue && this.options && this.options.length > 0) { diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts index bdc555d69c..25f7fca3b9 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/form.model.ts @@ -125,7 +125,7 @@ export class FormModel { if (field instanceof ContainerModel) { let container = field; result.push(container.field); - result.push(...container.children); + result.push(...container.field.fields); } } @@ -172,11 +172,11 @@ export class FormModel { if (field.params) { let originalField = field.params['field']; if (originalField.type === FormFieldTypes.DYNAMIC_TABLE) { - result.push(new ContainerModel(this, field)); + result.push(new ContainerModel(new FormFieldModel(this, field))); } } } else { - result.push(new ContainerModel(this, field)); + result.push(new ContainerModel(new FormFieldModel(this, field))); } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.spec.ts index 8b270c6af3..057dd34389 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.spec.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/tab.model.spec.ts @@ -53,7 +53,7 @@ describe('TabModel', () => { model.fields = []; expect(model.hasContent()).toBeFalsy(); - model.fields = [new ContainerModel(null, null)]; + model.fields = [new ContainerModel(null)]; expect(model.hasContent()).toBeTruthy(); }); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/text/text.widget.html b/ng2-components/ng2-activiti-form/src/components/widgets/text/text.widget.html index 95a46c3c44..b89c0851ae 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/text/text.widget.html +++ b/ng2-components/ng2-activiti-form/src/components/widgets/text/text.widget.html @@ -5,7 +5,7 @@ [attr.id]="field.id" [attr.required]="isRequired()" [(ngModel)]="field.value" - (ngModelChange)="checkVisibility(field)" + (ngModelChange)="onFieldChanged(field)" [disabled]="field.readOnly"> {{field.validationSummary}} diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts b/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts index ea96638258..b873ce0b33 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/widget.component.ts @@ -81,6 +81,7 @@ export class WidgetComponent implements AfterViewInit { /** @deprecated use onFieldChanged instead */ checkVisibility(field: FormFieldModel) { + console.log('checkVisibility is deprecated, use onFieldChanged instead'); this.fieldChanged.emit(field); } diff --git a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts index 7f1fde01e7..b5902ca619 100644 --- a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts +++ b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.spec.ts @@ -667,13 +667,13 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'LEFT_FORM_FIELD_ID'; - let contModel = new ContainerModel(fakeFormWithField, { + let contModel = new ContainerModel(new FormFieldModel(fakeFormWithField, { id: 'fake-container-id', type: FormFieldTypes.GROUP, name: 'fake-container-name', isVisible: true, visibilityCondition: visibilityObjTest - }); + })); fakeFormWithField.fields.push(contModel); service.refreshVisibility(fakeFormWithField); @@ -684,13 +684,13 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let contModel = new ContainerModel(fakeFormWithField, { + let contModel = new ContainerModel(new FormFieldModel(fakeFormWithField, { id: 'fake-container-id', type: FormFieldTypes.GROUP, name: 'fake-container-name', isVisible: true, visibilityCondition: visibilityObjTest - }); + })); service.refreshEntityVisibility(contModel.field); expect(contModel.isVisible).toBeFalsy(); }); diff --git a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts index 1eb5c1a7cc..ec29f89cda 100644 --- a/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts +++ b/ng2-components/ng2-activiti-form/src/services/widget-visibility.service.ts @@ -44,7 +44,8 @@ export class WidgetVisibilityService { } refreshEntityVisibility(element: FormFieldModel | TabModel) { - element.isVisible = this.evaluateVisibility(element.form, element.visibilityCondition); + let visible = this.evaluateVisibility(element.form, element.visibilityCondition); + element.isVisible = visible; } evaluateVisibility(form: FormModel, visibilityObj: WidgetVisibilityModel): boolean {