mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[REGRESSION-AFTER-CLI] Fixing --prod mode (#2633)
* FormRenderingService refactoring * Move common part to core and use in card view * Add documentation
This commit is contained in:
committed by
Eugenio Romano
parent
34f51e3558
commit
e1e9c735b4
@@ -45,7 +45,7 @@ Displays a configurable property list renderer.
|
||||
|
||||
## Details
|
||||
|
||||
You define the property list, the CardViewComponent does the rest. Each property represents a card view item (a row) in the card view component. At the time of writing two different kind of card view item (property type) is supported out of the box ([text](#card-text-item) item and [date](#card-date-item) item) but you can define your own custom types as well.
|
||||
You define the property list, the CardViewComponent does the rest. Each property represents a card view item (a row) in the card view component. At the time of writing three a few kind of card view item (property type) is supported out of the box (e.g: [text](#card-text-item) item and [date](#card-date-item) item) but you can define your own custom types as well.
|
||||
|
||||
### Editing
|
||||
|
||||
@@ -171,13 +171,16 @@ Card item components are loaded dynamically, which makes you able to define your
|
||||
|
||||
Let's consider you want to have a **stardate** type to display Captain Picard's birthday (47457.1). For this, you need to do the following steps.
|
||||
|
||||
#### 1. Define the model for the custom type
|
||||
#### 1. Define the Model for the custom type
|
||||
|
||||
Your model has to extend the CardViewBaseItemModel and implement the CardViewItem interface.
|
||||
Your model has to extend the **CardViewBaseItemModel** and implement the **CardViewItem** and **DynamicComponentModel** interface.
|
||||
*(You can check how the CardViewTextItemModel is implemented for further guidance.)*
|
||||
|
||||
```js
|
||||
export class CardViewStarDateItemModel extends CardViewBaseItemModel implements CardViewItem {
|
||||
import { CardViewBaseItemModel, CardViewItem, DynamicComponentModel } from 'ng2-alfresco-core';
|
||||
|
||||
export class CardViewStarDateItemModel extends CardViewBaseItemModel implements
|
||||
CardViewItem, DynamicComponentModel {
|
||||
type: string = 'star-date';
|
||||
|
||||
get displayValue() {
|
||||
@@ -190,13 +193,9 @@ export class CardViewStarDateItemModel extends CardViewBaseItemModel implements
|
||||
}
|
||||
```
|
||||
|
||||
The most important part of this model is the value of the **type** attribute. This is how the Card View component will be able to recognise which component is needed to render it dynamically.
|
||||
#### 2. Define the Component for the custom type
|
||||
|
||||
The type is a **hyphen-separated-lowercase-words** string (just like how I wrote it). This will be converted to a PascalCase (or UpperCamelCase) string to find the right component. In our case the Card View component will look for the CardView**StarDate**ItemComponent.
|
||||
|
||||
#### 2. Define the component for the custom type
|
||||
|
||||
As discussed in the previous step the only important thing here is the naming of your component class ( **CardViewStarDateItemComponent**). Since the selector is not used in this case, you can give any selector name to it, but it makes sense to follow the angular standards.
|
||||
Create your custom card view item component. Defining the selector is not important, being it a dinamically loaded component, so you can give any selector name to it, but it makes sense to follow the angular standards.
|
||||
|
||||
```js
|
||||
@Component({
|
||||
@@ -242,6 +241,27 @@ For Angular to be able to load your custom component dynamically, you have to re
|
||||
export class MyModule {}
|
||||
```
|
||||
|
||||
#### 4. Bind your custom component to the custom model type, enabling Angular's dynamic component loader to find it.
|
||||
|
||||
For mapping each type to their Component, there is the **CardItemTypeService**. This service extends the **DynamicComponentMapper** abstract class.
|
||||
This CardItemTypeService is responible for the type resolution, it contains all the default components (e.g.: text, date, etc...) also. In order to make your component available, you need to extend the list of possible components.
|
||||
|
||||
You can extend this list the following way:
|
||||
|
||||
```js
|
||||
@Component({
|
||||
...
|
||||
providers: [ CardItemTypeService ] // If you don't want to pollute the main instance of the CardItemTypeService service
|
||||
...
|
||||
})
|
||||
export class SomeParentComponent {
|
||||
|
||||
constructor(private cardItemTypeService: CardItemTypeService) {
|
||||
cardItemTypeService.setComponentTypeResolver('star-date', () => CardViewStarDateItemComponent);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Don't edit the See also section. Edit seeAlsoGraph.json and run config/generateSeeAlso.js -->
|
||||
<!-- seealso start -->
|
||||
## See also
|
||||
|
@@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DynamicComponentResolver } from 'ng2-alfresco-core';
|
||||
import {
|
||||
AttachWidgetComponent,
|
||||
FormFieldModel,
|
||||
@@ -22,7 +23,7 @@ import {
|
||||
UnknownWidgetComponent,
|
||||
UploadWidgetComponent
|
||||
} from './../components/widgets/index';
|
||||
import { DefaultTypeResolver, FormRenderingService } from './form-rendering.service';
|
||||
import { FormRenderingService } from './form-rendering.service';
|
||||
|
||||
describe('FormRenderingService', () => {
|
||||
|
||||
@@ -88,9 +89,9 @@ describe('FormRenderingService', () => {
|
||||
expect(
|
||||
() => service.setComponentTypeResolver(
|
||||
null,
|
||||
DefaultTypeResolver.fromType(UnknownWidgetComponent)
|
||||
DynamicComponentResolver.fromType(UnknownWidgetComponent)
|
||||
)
|
||||
).toThrowError('fieldType is null or not defined');
|
||||
).toThrowError('type is null or not defined');
|
||||
});
|
||||
|
||||
it('should require type resolver instance to set resolver for type', () => {
|
||||
@@ -106,13 +107,13 @@ describe('FormRenderingService', () => {
|
||||
expect(
|
||||
() => service.setComponentTypeResolver(
|
||||
FormFieldTypes.TEXT,
|
||||
DefaultTypeResolver.fromType(UnknownWidgetComponent)
|
||||
DynamicComponentResolver.fromType(UnknownWidgetComponent)
|
||||
)
|
||||
).toThrowError('already mapped, use override option if you intend replacing existing mapping.');
|
||||
});
|
||||
|
||||
it('should override existing resolver with explicit flag', () => {
|
||||
let customResolver = DefaultTypeResolver.fromType(UnknownWidgetComponent);
|
||||
let customResolver = DynamicComponentResolver.fromType(UnknownWidgetComponent);
|
||||
service.setComponentTypeResolver(FormFieldTypes.TEXT, customResolver, true);
|
||||
expect(service.getComponentTypeResolver(FormFieldTypes.TEXT)).toBe(customResolver);
|
||||
});
|
||||
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from 'ng2-alfresco-core';
|
||||
|
||||
import {
|
||||
AmountWidgetComponent,
|
||||
@@ -41,30 +42,33 @@ import {
|
||||
} from './../components/widgets/index';
|
||||
|
||||
@Injectable()
|
||||
export class FormRenderingService {
|
||||
export class FormRenderingService extends DynamicComponentMapper {
|
||||
|
||||
private types: { [key: string]: ComponentTypeResolver } = {
|
||||
'text': DefaultTypeResolver.fromType(TextWidgetComponent),
|
||||
'string': DefaultTypeResolver.fromType(TextWidgetComponent),
|
||||
'integer': DefaultTypeResolver.fromType(NumberWidgetComponent),
|
||||
'multi-line-text': DefaultTypeResolver.fromType(MultilineTextWidgetComponentComponent),
|
||||
'boolean': DefaultTypeResolver.fromType(CheckboxWidgetComponent),
|
||||
'dropdown': DefaultTypeResolver.fromType(DropdownWidgetComponent),
|
||||
'date': DefaultTypeResolver.fromType(DateWidgetComponent),
|
||||
'amount': DefaultTypeResolver.fromType(AmountWidgetComponent),
|
||||
'radio-buttons': DefaultTypeResolver.fromType(RadioButtonsWidgetComponent),
|
||||
'hyperlink': DefaultTypeResolver.fromType(HyperlinkWidgetComponent),
|
||||
'readonly-text': DefaultTypeResolver.fromType(DisplayTextWidgetComponentComponent),
|
||||
'typeahead': DefaultTypeResolver.fromType(TypeaheadWidgetComponent),
|
||||
'people': DefaultTypeResolver.fromType(PeopleWidgetComponent),
|
||||
'functional-group': DefaultTypeResolver.fromType(FunctionalGroupWidgetComponent),
|
||||
'dynamic-table': DefaultTypeResolver.fromType(DynamicTableWidgetComponent),
|
||||
'container': DefaultTypeResolver.fromType(ContainerWidgetComponent),
|
||||
'group': DefaultTypeResolver.fromType(ContainerWidgetComponent),
|
||||
'document': DefaultTypeResolver.fromType(DocumentWidgetComponent)
|
||||
protected defaultValue: Type<{}> = UnknownWidgetComponent;
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {
|
||||
'text': DynamicComponentResolver.fromType(TextWidgetComponent),
|
||||
'string': DynamicComponentResolver.fromType(TextWidgetComponent),
|
||||
'integer': DynamicComponentResolver.fromType(NumberWidgetComponent),
|
||||
'multi-line-text': DynamicComponentResolver.fromType(MultilineTextWidgetComponentComponent),
|
||||
'boolean': DynamicComponentResolver.fromType(CheckboxWidgetComponent),
|
||||
'dropdown': DynamicComponentResolver.fromType(DropdownWidgetComponent),
|
||||
'date': DynamicComponentResolver.fromType(DateWidgetComponent),
|
||||
'amount': DynamicComponentResolver.fromType(AmountWidgetComponent),
|
||||
'radio-buttons': DynamicComponentResolver.fromType(RadioButtonsWidgetComponent),
|
||||
'hyperlink': DynamicComponentResolver.fromType(HyperlinkWidgetComponent),
|
||||
'readonly-text': DynamicComponentResolver.fromType(DisplayTextWidgetComponentComponent),
|
||||
'typeahead': DynamicComponentResolver.fromType(TypeaheadWidgetComponent),
|
||||
'people': DynamicComponentResolver.fromType(PeopleWidgetComponent),
|
||||
'functional-group': DynamicComponentResolver.fromType(FunctionalGroupWidgetComponent),
|
||||
'dynamic-table': DynamicComponentResolver.fromType(DynamicTableWidgetComponent),
|
||||
'container': DynamicComponentResolver.fromType(ContainerWidgetComponent),
|
||||
'group': DynamicComponentResolver.fromType(ContainerWidgetComponent),
|
||||
'document': DynamicComponentResolver.fromType(DocumentWidgetComponent)
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.types['upload'] = (field: FormFieldModel): Type<{}> => {
|
||||
if (field) {
|
||||
let params = field.params;
|
||||
@@ -76,47 +80,4 @@ export class FormRenderingService {
|
||||
return UnknownWidgetComponent;
|
||||
};
|
||||
}
|
||||
|
||||
getComponentTypeResolver(fieldType: string, defaultValue: Type<{}> = UnknownWidgetComponent): ComponentTypeResolver {
|
||||
if (fieldType) {
|
||||
return this.types[fieldType] || DefaultTypeResolver.fromType(defaultValue);
|
||||
}
|
||||
return DefaultTypeResolver.fromType(defaultValue);
|
||||
}
|
||||
|
||||
setComponentTypeResolver(fieldType: string, resolver: ComponentTypeResolver, override: boolean = false) {
|
||||
if (!fieldType) {
|
||||
throw new Error(`fieldType is null or not defined`);
|
||||
}
|
||||
|
||||
if (!resolver) {
|
||||
throw new Error(`resolver is null or not defined`);
|
||||
}
|
||||
|
||||
let existing = this.types[fieldType];
|
||||
if (existing && !override) {
|
||||
throw new Error(`already mapped, use override option if you intend replacing existing mapping.`);
|
||||
}
|
||||
|
||||
this.types[fieldType] = resolver;
|
||||
}
|
||||
|
||||
resolveComponentType(field: FormFieldModel, defaultValue: Type<{}> = UnknownWidgetComponent): Type<{}> {
|
||||
if (field) {
|
||||
let resolver = this.getComponentTypeResolver(field.type, defaultValue);
|
||||
return resolver(field);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type ComponentTypeResolver = (field: FormFieldModel) => Type<{}>;
|
||||
|
||||
export class DefaultTypeResolver {
|
||||
static fromType(type: Type<{}>): ComponentTypeResolver {
|
||||
return (field: FormFieldModel) => {
|
||||
return type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -39,6 +39,7 @@ import { AuthGuardBpm } from './src/services/auth-guard-bpm.service';
|
||||
import { AuthGuardEcm } from './src/services/auth-guard-ecm.service';
|
||||
import { AuthGuard } from './src/services/auth-guard.service';
|
||||
import { AuthenticationService } from './src/services/authentication.service';
|
||||
import { CardItemTypeService } from './src/services/card-item-types.service';
|
||||
import { CommentProcessService } from './src/services/comment-process.service';
|
||||
import { ContentService } from './src/services/content.service';
|
||||
import { CookieService } from './src/services/cookie.service';
|
||||
@@ -98,6 +99,8 @@ export { AlfrescoTranslateLoader } from './src/services/translate-loader.service
|
||||
export { AppConfigService } from './src/services/app-config.service';
|
||||
export { ThumbnailService } from './src/services/thumbnail.service';
|
||||
export { UploadService } from './src/services/upload.service';
|
||||
export { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from './src/services/dynamic-component-mapper.service';
|
||||
export { CardItemTypeService } from './src/services/card-item-types.service';
|
||||
export { CardViewUpdateService } from './src/services/card-view-update.service';
|
||||
export { UpdateNotification } from './src/services/card-view-update.service';
|
||||
export { ClickNotification } from './src/services/card-view-update.service';
|
||||
@@ -167,6 +170,7 @@ export * from './src/events/base-ui.event';
|
||||
export * from './src/events/folder-created.event';
|
||||
export * from './src/events/file.event';
|
||||
|
||||
export * from './src/models/card-view-baseitem.model';
|
||||
export * from './src/models/card-view-textitem.model';
|
||||
export * from './src/models/card-view-mapitem.model';
|
||||
export * from './src/models/card-view-dateitem.model';
|
||||
@@ -219,6 +223,7 @@ export function providers() {
|
||||
PeopleProcessService,
|
||||
AppsProcessService,
|
||||
CommentProcessService,
|
||||
CardItemTypeService,
|
||||
AppConfigService
|
||||
];
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
|
||||
import { CardViewItem } from '../../interface/card-view-item.interface';
|
||||
import { CardItemTypeService } from '../../services/card-item-types.service';
|
||||
import { CardViewContentProxyDirective } from './card-view-content-proxy.directive';
|
||||
import { CardViewItemDispatcherComponent } from './card-view-item-dispatcher.component';
|
||||
|
||||
@@ -37,9 +38,13 @@ export class CardViewShinyCustomElementItemComponent {
|
||||
describe('CardViewItemDispatcherComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<CardViewItemDispatcherComponent>;
|
||||
let cardItemTypeService: CardItemTypeService;
|
||||
let component: CardViewItemDispatcherComponent;
|
||||
|
||||
beforeEach(async(() => {
|
||||
cardItemTypeService = new CardItemTypeService();
|
||||
cardItemTypeService.setComponentTypeResolver('shiny-custom-element', () => CardViewShinyCustomElementItemComponent);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [],
|
||||
declarations: [
|
||||
@@ -47,7 +52,7 @@ describe('CardViewItemDispatcherComponent', () => {
|
||||
CardViewShinyCustomElementItemComponent,
|
||||
CardViewContentProxyDirective
|
||||
],
|
||||
providers: []
|
||||
providers: [ { provide: CardItemTypeService, useValue: cardItemTypeService } ]
|
||||
});
|
||||
|
||||
// entryComponents are not supported yet on TestBed, that is why this ugly workaround:
|
||||
|
@@ -20,10 +20,10 @@ import {
|
||||
ComponentFactoryResolver,
|
||||
Input,
|
||||
OnChanges,
|
||||
Type,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { CardViewItem } from '../../interface/card-view-item.interface';
|
||||
import { CardItemTypeService } from '../../services/card-item-types.service';
|
||||
import { CardViewContentProxyDirective } from './card-view-content-proxy.directive';
|
||||
|
||||
@Component({
|
||||
@@ -46,7 +46,8 @@ export class CardViewItemDispatcherComponent implements OnChanges {
|
||||
public ngOnInit;
|
||||
public ngDoCheck;
|
||||
|
||||
constructor(private resolver: ComponentFactoryResolver) {
|
||||
constructor(private cardItemTypeService: CardItemTypeService,
|
||||
private resolver: ComponentFactoryResolver) {
|
||||
const dynamicLifecycleMethods = [
|
||||
'ngOnInit',
|
||||
'ngDoCheck',
|
||||
@@ -72,11 +73,8 @@ export class CardViewItemDispatcherComponent implements OnChanges {
|
||||
}
|
||||
|
||||
private loadComponent() {
|
||||
const upperCamelCasedType = this.getUpperCamelCase(this.property.type),
|
||||
className = `CardView${upperCamelCasedType}ItemComponent`;
|
||||
const factoryClass = this.cardItemTypeService.resolveComponentType(this.property);
|
||||
|
||||
const factories = Array.from(this.resolver['_factories'].keys());
|
||||
const factoryClass = <Type<any>> factories.find((x: any) => x.name === className);
|
||||
const factory = this.resolver.resolveComponentFactory(factoryClass);
|
||||
this.componentReference = this.content.viewContainerRef.createComponent(factory);
|
||||
|
||||
@@ -84,11 +82,6 @@ export class CardViewItemDispatcherComponent implements OnChanges {
|
||||
this.componentReference.instance.property = this.property;
|
||||
}
|
||||
|
||||
private getUpperCamelCase(type: string): string {
|
||||
const camelCasedType = type.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
||||
return camelCasedType[0].toUpperCase() + camelCasedType.substr(1);
|
||||
}
|
||||
|
||||
private proxy(methodName, ...args) {
|
||||
if (this.componentReference.instance[methodName]) {
|
||||
this.componentReference.instance[methodName].apply(this.componentReference.instance, args);
|
||||
|
@@ -25,13 +25,14 @@
|
||||
|
||||
import * as moment from 'moment';
|
||||
import { CardViewItem } from '../interface/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model';
|
||||
|
||||
export interface CardViewDateItemProperties extends CardViewItemProperties {
|
||||
format?: string;
|
||||
}
|
||||
|
||||
export class CardViewDateItemModel extends CardViewBaseItemModel implements CardViewItem {
|
||||
export class CardViewDateItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
type: string = 'date';
|
||||
format: string;
|
||||
|
||||
|
@@ -24,9 +24,10 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interface/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model';
|
||||
|
||||
export class CardViewMapItemModel extends CardViewBaseItemModel implements CardViewItem {
|
||||
export class CardViewMapItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
type: string = 'map';
|
||||
value: Map<string, string>;
|
||||
|
||||
|
@@ -24,12 +24,13 @@
|
||||
*/
|
||||
|
||||
import { CardViewItem } from '../interface/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model';
|
||||
|
||||
export interface CardViewTextItemProperties extends CardViewItemProperties {
|
||||
multiline?: boolean;
|
||||
}
|
||||
export class CardViewTextItemModel extends CardViewBaseItemModel implements CardViewItem {
|
||||
export class CardViewTextItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
type: string = 'text';
|
||||
multiline: boolean;
|
||||
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import { CardViewDateItemComponent } from '../components/view/card-view-dateitem.component';
|
||||
import { CardViewMapItemComponent } from '../components/view/card-view-mapitem.component';
|
||||
import { CardViewTextItemComponent } from '../components/view/card-view-textitem.component';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../services/dynamic-component-mapper.service';
|
||||
|
||||
@Injectable()
|
||||
export class CardItemTypeService extends DynamicComponentMapper {
|
||||
|
||||
protected defaultValue: Type<{}> = CardViewTextItemComponent;
|
||||
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {
|
||||
'text': DynamicComponentResolver.fromType(CardViewTextItemComponent),
|
||||
'date': DynamicComponentResolver.fromType(CardViewDateItemComponent),
|
||||
'map': DynamicComponentResolver.fromType(CardViewMapItemComponent)
|
||||
};
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Type } from '@angular/core';
|
||||
|
||||
export interface DynamicComponentModel { type: string; }
|
||||
export type DynamicComponentResolveFunction = (model: DynamicComponentModel) => Type<{}>;
|
||||
export class DynamicComponentResolver {
|
||||
static fromType(type: Type<{}>): DynamicComponentResolveFunction {
|
||||
return (model: DynamicComponentModel) => {
|
||||
return type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class DynamicComponentMapper {
|
||||
|
||||
protected defaultValue: Type<{}> = undefined;
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {};
|
||||
|
||||
getComponentTypeResolver(type: string, defaultValue: Type<{}> = this.defaultValue): DynamicComponentResolveFunction {
|
||||
if (type) {
|
||||
return this.types[type] || DynamicComponentResolver.fromType(defaultValue);
|
||||
}
|
||||
return DynamicComponentResolver.fromType(defaultValue);
|
||||
}
|
||||
|
||||
setComponentTypeResolver(type: string, resolver: DynamicComponentResolveFunction, override: boolean = false) {
|
||||
if (!type) {
|
||||
throw new Error(`type is null or not defined`);
|
||||
}
|
||||
|
||||
if (!resolver) {
|
||||
throw new Error(`resolver is null or not defined`);
|
||||
}
|
||||
|
||||
let existing = this.types[type];
|
||||
if (existing && !override) {
|
||||
throw new Error(`already mapped, use override option if you intend replacing existing mapping.`);
|
||||
}
|
||||
|
||||
this.types[type] = resolver;
|
||||
}
|
||||
|
||||
resolveComponentType(model: DynamicComponentModel, defaultValue: Type<{}> = this.defaultValue): Type<{}> {
|
||||
if (model) {
|
||||
let resolver = this.getComponentTypeResolver(model.type, defaultValue);
|
||||
return resolver(model);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user