-
-
Save devtronic/807e8bfc712330ef13a5c9b8bf5a71cf to your computer and use it in GitHub Desktop.
Form builder tab group example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// tab-group.type.ts | |
import {TabGroupOptions} from './tab-group.options'; | |
import {AbstractLayoutType, Constructor, FormModel} from '@mintware-de/form-builder'; | |
import {TabGroupComponent} from './tab-group.component'; | |
export class TabGroup<T extends FormModel = FormModel> extends AbstractLayoutType<TabGroupOptions<any>> { | |
public readonly component: Constructor = TabGroupComponent; | |
constructor(options: TabGroupOptions<T>) { | |
super(options); | |
} | |
} | |
// tab-group.component.ts | |
import {AfterContentInit, Component, OnDestroy} from '@angular/core'; | |
import {AbstractControl} from '@angular/forms'; | |
import {TabGroupOptions} from './tab-group.options'; | |
import {AbstractLayoutComponent, AbstractLayoutType, IGroupTypeOptions} from '@mintware-de/form-builder'; | |
import {Subscription} from 'rxjs'; | |
@Component({ | |
selector: 'app-tab-group', | |
template: ` | |
<mat-tab-group> | |
<mat-tab *ngFor="let tab of mwFieldType.options.tabs; index as tabIndex"> | |
<ng-template mat-tab-label> | |
<i style="margin-right: 8px" class="fas fa-fw"></i> | |
{{tab.caption }} | |
<i style="margin-left: 8px; color: red" | |
class="fas fa-fw" | |
[ngClass]="{'fa-exclamation-circle': tabsWithWarning[tabIndex] }"></i> | |
</ng-template> | |
<mat-card-content> | |
<ng-container *ngFor="let controlName of tab.controls" | |
mwFormSlot | |
[mwFieldName]="controlName"></ng-container> | |
</mat-card-content> | |
</mat-tab> | |
</mat-tab-group> | |
`, | |
}) | |
export class TabGroupComponent extends AbstractLayoutComponent<AbstractLayoutType<TabGroupOptions<any>>> | |
implements AfterContentInit, OnDestroy { | |
public tabsWithWarning: boolean[] = []; | |
private subscriptions: Subscription[] = []; | |
public ngAfterContentInit(): void { | |
super.ngAfterContentInit(); | |
const realControlsPerTab: AbstractControl[][] = []; | |
this.mwFieldType.options.tabs.forEach((tab, index) => { | |
realControlsPerTab[index] = []; | |
tab.controls.forEach((ctrlName: string) => { | |
this.nestedElements(ctrlName).forEach((path) => { | |
const el = this.mwFormGroup.get(path); | |
if (el) { | |
realControlsPerTab[index].push(el); | |
} | |
}); | |
}); | |
}); | |
realControlsPerTab.forEach((controls, index) => { | |
const updateFunction = () => { | |
this.mwFormGroup.updateValueAndValidity(); | |
this.tabsWithWarning[index] = controls.reduce((valid, ctrl) => valid || ctrl.invalid, false); | |
}; | |
this.subscriptions.push(...controls.map((ctrl) => ctrl.statusChanges.subscribe(() => { | |
updateFunction(); | |
}))); | |
}); | |
} | |
public ngOnDestroy(): void { | |
this.subscriptions.forEach((s) => s.unsubscribe()); | |
} | |
private nestedElements(fieldName: string): string[] { | |
if (!(this.mwFieldType.options.model[fieldName] instanceof AbstractLayoutType)) { | |
return [this.fieldPaths[fieldName]]; | |
} | |
const childrenToCheck: Array<{ path: string, layout: AbstractLayoutType<IGroupTypeOptions> }> = [ | |
{path: this.fieldPaths[fieldName], layout: this.mwFieldType.options.model[fieldName]}, | |
]; | |
const allElements: string[] = []; | |
do { | |
// @ts-ignore | |
const {path, layout} = childrenToCheck.shift(); | |
Object.keys(layout.options.model).forEach((k) => { | |
if (layout.options.model[k] instanceof AbstractLayoutType) { | |
childrenToCheck.push({path, layout: layout.options.model[k]}); | |
} else { | |
const childPath = [path, k].filter((x) => x).join('.'); | |
if (childPath !== '') { | |
allElements.push(childPath); | |
} | |
} | |
}); | |
} while (childrenToCheck.length > 0); | |
return allElements; | |
} | |
} | |
// tab-group.options.ts | |
import {FormModel, IGroupTypeOptions} from '@mintware-de/form-builder'; | |
export interface TabGroupOptions<T extends FormModel> extends IGroupTypeOptions { | |
model: T; | |
readonly tabs: Array<{ caption: string, controls: Array<keyof T>}>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment