mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
#967 rework container model structure
- now FormFieldModel provides information about columns and child fields - greatly simplified models - visibility engine fixes
This commit is contained in:
parent
e114534bc5
commit
ee56a1faa6
@ -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: `<div #container></div>`
|
||||
template: `
|
||||
<div [hidden]="!field.isVisible">
|
||||
<div #container></div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
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<FormFieldModel> = new EventEmitter<FormFieldModel>();
|
||||
|
||||
private componentRef: ComponentRef<{}>;
|
||||
|
||||
constructor(
|
||||
@ -54,12 +54,10 @@ export class FormFieldComponent implements OnInit {
|
||||
this.componentRef = this.container.createComponent(factory/*, 0, this.injector*/);
|
||||
let instance = <WidgetComponent>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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
<div>{{content?.isVisible}}</div>
|
||||
<div class="container-widget">
|
||||
<div *ngIf="content?.isGroup() && content?.isVisible" class="container-widget__header">
|
||||
<h4 class="container-widget__header-text" id="container-header"
|
||||
@ -15,7 +16,7 @@
|
||||
<div *ngFor="let col of content.columns" class="mdl-cell mdl-cell--{{col.size}}-col">
|
||||
<div class="mdl-grid" *ngIf="col.hasFields()">
|
||||
<div *ngFor="let field of col.fields" class="mdl-cell mdl-cell--12-col">
|
||||
<form-field [field]="field" [hidden]="!field.isVisible"></form-field>
|
||||
<form-field [field]="field"></form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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: '<type>',
|
||||
id: '<id>',
|
||||
name: '<name>',
|
||||
type: '<type>',
|
||||
tab: '<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: '<type>',
|
||||
id: '<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();
|
||||
});
|
||||
|
||||
|
@ -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 = <number> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
|
||||
export class ContainerColumnModel {
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 = <boolean>json.enableFractions;
|
||||
this.currency = json.currency;
|
||||
this._value = this.parseValue(json);
|
||||
|
||||
// <container>
|
||||
this.numberOfColumns = <number> 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);
|
||||
});
|
||||
}
|
||||
// </container>
|
||||
}
|
||||
|
||||
if (this.hasEmptyValue && this.options && this.options.length > 0) {
|
||||
|
@ -125,7 +125,7 @@ export class FormModel {
|
||||
if (field instanceof ContainerModel) {
|
||||
let container = <ContainerModel> 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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
[attr.id]="field.id"
|
||||
[attr.required]="isRequired()"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="checkVisibility(field)"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly">
|
||||
<label class="mdl-textfield__label" [attr.for]="field.id">{{field.name}}</label>
|
||||
<span *ngIf="field.validationSummary" class="mdl-textfield__error">{{field.validationSummary}}</span>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user