diff --git a/lib/core/form/components/form-renderer.component.spec.ts b/lib/core/form/components/form-renderer.component.spec.ts
index 8fbde5ba22..7300165775 100644
--- a/lib/core/form/components/form-renderer.component.spec.ts
+++ b/lib/core/form/components/form-renderer.component.spec.ts
@@ -329,15 +329,15 @@ describe('Form Renderer Component', () => {
formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null , false, false);
fixture.detectChanges();
await fixture.whenStable();
- const formSizedElement = fixture.nativeElement.querySelector('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container section.adf-grid-list-column-view');
+ const formSizedElement = fixture.nativeElement.querySelector('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div.adf-grid-list');
expectElementToBeVisible(formSizedElement);
- const sectionGridElement: HTMLElement[] = fixture.nativeElement.querySelectorAll('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container section .adf-grid-list-single-column');
+ const sectionGridElement: HTMLElement[] = fixture.nativeElement.querySelectorAll('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div .adf-grid-list-item');
sectionGridElement.forEach((element) => {
- expect(element.style['width']).toBe('50%', 'Elemens is wrong sized for this section');
+ expect(element.style['grid-area']).toBe('auto / auto / span 1 / span 1', 'Elemens is wrong sized for this section');
});
- const fullWidthElement = fixture.nativeElement.querySelector('#field-d52ada4e-cbdc-4f0c-a480-5b85fa00e4f8-container section.adf-grid-list-column-view .adf-grid-list-single-column');
- expect(fullWidthElement.style['width']).toBe('100%');
+ const fullWidthElement = fixture.nativeElement.querySelector('#field-d52ada4e-cbdc-4f0c-a480-5b85fa00e4f8-container div.adf-grid-list .adf-grid-list-item');
+ expect(fullWidthElement.style['grid-area']).toBe('auto / auto / span 1 / span 2');
});
it('[C309655] - Should display validation error message when Number widget has invalid value', async () => {
diff --git a/lib/core/form/components/widgets/container/container.widget.html b/lib/core/form/components/widgets/container/container.widget.html
index ab26552b29..bc7ae6cea5 100644
--- a/lib/core/form/components/widgets/container/container.widget.html
+++ b/lib/core/form/components/widgets/container/container.widget.html
@@ -12,11 +12,13 @@
-
-
diff --git a/lib/core/form/components/widgets/container/container.widget.scss b/lib/core/form/components/widgets/container/container.widget.scss
index b360e79854..502a36e7b1 100644
--- a/lib/core/form/components/widgets/container/container.widget.scss
+++ b/lib/core/form/components/widgets/container/container.widget.scss
@@ -57,14 +57,10 @@
}
.adf-grid-list {
- display: flex;
- flex-wrap: wrap;
- margin-left: -1%;
- margin-right: -1%;
+ display: grid;
}
.adf-grid-list-item {
- flex-grow: 1;
box-sizing: border-box;
padding-left: 1%;
padding-right: 1%;
@@ -119,5 +115,9 @@
width: 80%;
}
+ adf-form-field {
+ width: 100%;
+ }
+
}
}
diff --git a/lib/core/form/components/widgets/container/container.widget.spec.ts b/lib/core/form/components/widgets/container/container.widget.spec.ts
index 7d902264bd..be90cd7f8c 100644
--- a/lib/core/form/components/widgets/container/container.widget.spec.ts
+++ b/lib/core/form/components/widgets/container/container.widget.spec.ts
@@ -17,7 +17,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ContainerColumnModel } from './../core/container-column.model';
import { FormFieldTypes } from './../core/form-field-types';
import { FormFieldModel } from './../core/form-field.model';
import { FormModel } from './../core/form.model';
@@ -103,7 +102,7 @@ describe('ContainerWidgetComponent', () => {
it('should send an event when a value is changed in the form', (done) => {
const fakeForm = new FormModel();
- const fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'});
+ const fakeField = new FormFieldModel(fakeForm, { id: 'fakeField', value: 'fakeValue' });
widget.fieldChanged.subscribe((field) => {
expect(field).not.toBe(null);
expect(field.id).toBe('fakeField');
@@ -117,30 +116,22 @@ describe('ContainerWidgetComponent', () => {
describe('fields', () => {
it('should serializes the content fields', () => {
- const field1 = {id: '1'},
- field2 = {id: '2'},
- field3 = {id: '3'},
- field4 = {id: '4'},
- field5 = {id: '5'},
- field6 = {id: '6'};
+ const form = new FormModel();
+ const json = {
+ id: 'test',
+ name: 'test',
+ type: 'container',
+ tab: null,
+ fields: {
+ '1' : [{ id: '1' }, { id: '2' }, { id: '3' }],
+ '2' : [{ id: '4' }, { id: '5' }],
+ '3' : [{ id: '6' }]
+ }
+ };
- const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel()));
- container.columns = [
- { fields: [
- field1,
- field2,
- field3
- ] },
- { fields: [
- field4,
- field5
- ] },
- { fields: [
- field6
- ] }
- ];
-
- widget.content = container;
+ const field = new FormFieldModel(form, json);
+ widget.field = field;
+ widget.ngOnInit();
expect(widget.fields[0].id).toEqual('1');
expect(widget.fields[1].id).toEqual('4');
@@ -152,6 +143,99 @@ describe('ContainerWidgetComponent', () => {
expect(widget.fields[7]).toEqual(undefined);
expect(widget.fields[8]).toEqual(undefined);
});
+
+ it('should serializes the content fields with rowspan', () => {
+ const form = new FormModel();
+ const json = {
+ id: 'test',
+ name: 'test',
+ type: 'container',
+ tab: null,
+ fields: {
+ '1': [
+ {
+ id: 'a',
+ colspan: 2,
+ rowspan: 1
+ },
+ {
+ id: 'b'
+ },
+ {
+ id: 'c'
+ },
+ {
+ id: 'd'
+ },
+ {
+ id: 'e',
+ colspan: 3
+ },
+ {
+ id: 'f'
+ },
+ {
+ id: 'g'
+ },
+ {
+ id: 'h',
+ colspan: 2
+ }
+ ],
+ '2': [
+ {
+ id: '1',
+ rowspan: 3
+ },
+ {
+ id: '2',
+ rowspan: 2,
+ colspan: 2
+ },
+ {
+ id: '3'
+ }
+ ],
+ '3': [
+ {
+ id: 'white'
+ },
+ {
+ id: 'black'
+ },
+ {
+ id: 'green',
+ rowspan: 2
+ },
+ {
+ id: 'yellow'
+ }
+ ]
+ }
+ };
+ const field = new FormFieldModel(form, json);
+ widget.field = field;
+ widget.ngOnInit();
+
+ expect(widget.fields.length).toEqual(17);
+ expect(widget.fields[0].id).toEqual('a');
+ expect(widget.fields[1].id).toEqual('white');
+ expect(widget.fields[2].id).toEqual('b');
+ expect(widget.fields[3].id).toEqual('1');
+ expect(widget.fields[4].id).toEqual('black');
+ expect(widget.fields[5].id).toEqual('c');
+ expect(widget.fields[6].id).toEqual('green');
+ expect(widget.fields[7].id).toEqual('d');
+ expect(widget.fields[8].id).toEqual('e');
+ expect(widget.fields[9].id).toEqual('f');
+ expect(widget.fields[10].id).toEqual('2');
+ expect(widget.fields[11].id).toEqual('g');
+ expect(widget.fields[12].id).toEqual('h');
+ expect(widget.fields[13].id).toEqual('yellow');
+ expect(widget.fields[14]).toEqual(undefined);
+ expect(widget.fields[15].id).toEqual('3');
+ expect(widget.fields[16]).toEqual(undefined);
+ });
});
describe('getColumnWith', () => {
diff --git a/lib/core/form/components/widgets/container/container.widget.ts b/lib/core/form/components/widgets/container/container.widget.ts
index f0ac4e0c78..c77523efe1 100644
--- a/lib/core/form/components/widgets/container/container.widget.ts
+++ b/lib/core/form/components/widgets/container/container.widget.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
- /* tslint:disable:component-selector */
+/* tslint:disable:component-selector */
import { AfterViewInit, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormService } from './../../../services/form.service';
@@ -43,9 +43,11 @@ import { ContainerWidgetComponentModel } from './container.widget.model';
export class ContainerWidgetComponent extends WidgetComponent implements OnInit, AfterViewInit {
content: ContainerWidgetComponentModel;
+ numberOfColumns: number;
+ fields: FormFieldModel[];
constructor(public formService: FormService) {
- super(formService);
+ super(formService);
}
onExpanderClicked() {
@@ -57,34 +59,90 @@ export class ContainerWidgetComponent extends WidgetComponent implements OnInit,
ngOnInit() {
if (this.field) {
this.content = new ContainerWidgetComponentModel(this.field);
+ this.getNumberOfColumnsFromTheBiggestBetweenJsonAndColumnsLengthOrOne();
+ this.fields = this.getFields();
}
}
+ private getNumberOfColumnsFromTheBiggestBetweenJsonAndColumnsLengthOrOne() {
+ this.numberOfColumns = (this.content.json?.numberOfColumns || 1) > (this.content.columns?.length || 1) ?
+ (this.content.json?.numberOfColumns || 1) :
+ (this.content.columns?.length || 1);
+ }
+
/**
* Serializes column fields
*/
- get fields(): FormFieldModel[] {
- const fields = [];
+ private getFields(): FormFieldModel[] {
+ const { size, rowspanOffset, numberOfColumnElementsToBeProcessedRemaining , fields } = this.initializeHelpers();
- let rowContainsElement = true,
- rowIndex = 0;
-
- while (rowContainsElement) {
- rowContainsElement = false;
- for (let i = 0; i < this.content.columns.length; i++ ) {
- const field = this.content.columns[i].fields[rowIndex];
- if (field) {
- rowContainsElement = true;
+ for (let i = 0; i < size; i++) {
+ let fieldExist = false;
+ let columnIndex = 0;
+ while (columnIndex < this.numberOfColumns) {
+ let field: FormFieldModel;
+ if (rowspanOffset[columnIndex] > 0) {
+ this.decreaseRowspanOffsetForColumn(rowspanOffset, columnIndex);
+ } else {
+ field = this.getNextFieldToAdd(columnIndex, numberOfColumnElementsToBeProcessedRemaining, field);
+ fields.push(field);
+ if (field) {
+ fieldExist = true;
+ }
+ this.updateColumnsRowspanOffsetWithFieldRowspan(field, rowspanOffset, columnIndex);
+ numberOfColumnElementsToBeProcessedRemaining[columnIndex] = numberOfColumnElementsToBeProcessedRemaining[columnIndex] - 1;
}
-
- fields.push(field);
+ columnIndex = columnIndex + (field?.colspan || 1);
+ }
+ if (!fieldExist) {
+ i = this.deleteLastEmptyRowAndExit(fields, i, size);
}
- rowIndex++;
}
-
return fields;
}
+ private updateColumnsRowspanOffsetWithFieldRowspan(field: FormFieldModel, rowspanOffset: any[], columnIndex: number) {
+ for (let k = 0; k < (field?.colspan || 1); k++) {
+ rowspanOffset[columnIndex + k] = field?.rowspan > 0 ? field?.rowspan - 1 : 0;
+ }
+ }
+
+ private getNextFieldToAdd(columnIndex: number, numberOfColumnElementsToBeProcessedRemaining: any[], field: FormFieldModel): FormFieldModel {
+ const rowToCompute = (this.content.columns[columnIndex]?.fields?.length || 0) - numberOfColumnElementsToBeProcessedRemaining[columnIndex];
+ field = this.content.columns[columnIndex]?.fields[rowToCompute];
+ return field;
+ }
+
+ private decreaseRowspanOffsetForColumn(rowspanOffset: any[], columnIndex: number) {
+ rowspanOffset[columnIndex] = rowspanOffset[columnIndex] - 1;
+ }
+
+ private initializeHelpers(): {
+ size: number;
+ rowspanOffset: number[];
+ numberOfColumnElementsToBeProcessedRemaining: number[];
+ fields: FormFieldModel[];
+ } {
+ const fields = [];
+ const numberOfColumnElementsToBeProcessedRemaining: number[] = [];
+ const rowspanOffset: number[] = [];
+ let size = 0;
+ for (let i = 0; i < this.numberOfColumns; i++) {
+ numberOfColumnElementsToBeProcessedRemaining.push(this.content.columns[i]?.fields?.length || 0);
+ rowspanOffset[i] = 0;
+ size += (this.content.columns[i]?.fields?.length || 0);
+ }
+ return { size, rowspanOffset, numberOfColumnElementsToBeProcessedRemaining, fields };
+ }
+
+ private deleteLastEmptyRowAndExit(fields: FormFieldModel[], i: number, size: number) {
+ for (let j = 0; j < this.numberOfColumns; j++) {
+ fields.pop();
+ }
+ i = size;
+ return i;
+ }
+
/**
* Calculate the column width based on the numberOfColumns and current field's colspan property
*
diff --git a/lib/core/form/components/widgets/core/form-field.model.ts b/lib/core/form/components/widgets/core/form-field.model.ts
index dd65b609be..5dd787af12 100644
--- a/lib/core/form/components/widgets/core/form-field.model.ts
+++ b/lib/core/form/components/widgets/core/form-field.model.ts
@@ -152,6 +152,7 @@ export class FormFieldModel extends FormWidgetModel {
this.restIdProperty = json.restIdProperty;
this.restLabelProperty = json.restLabelProperty;
this.colspan = json.colspan;
+ this.rowspan = json.rowspan;
this.minLength = json.minLength || 0;
this.maxLength = json.maxLength || 0;
this.minValue = json.minValue;
diff --git a/lib/core/form/components/widgets/core/form.model.ts b/lib/core/form/components/widgets/core/form.model.ts
index 88721c13ff..163bc1689d 100644
--- a/lib/core/form/components/widgets/core/form.model.ts
+++ b/lib/core/form/components/widgets/core/form.model.ts
@@ -99,7 +99,7 @@ export class FormModel {
this.className = json.className || '';
this.variables = json.variables || [];
this.processVariables = json.processVariables || [];
- this.enableFixedSpace = enableFixedSpace;
+ this.enableFixedSpace = enableFixedSpace || true;
const tabCache: FormWidgetModelCache = {};