[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:
Popovics András
2017-11-09 17:12:41 +00:00
committed by Eugenio Romano
parent 34f51e3558
commit e1e9c735b4
11 changed files with 181 additions and 93 deletions

View File

@@ -45,7 +45,7 @@ Displays a configurable property list renderer.
## Details ## 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 ### 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. 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.)* *(You can check how the CardViewTextItemModel is implemented for further guidance.)*
```js ```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'; type: string = 'star-date';
get displayValue() { 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. 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.
#### 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.
```js ```js
@Component({ @Component({
@@ -242,6 +241,27 @@ For Angular to be able to load your custom component dynamically, you have to re
export class MyModule {} 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 --> <!-- Don't edit the See also section. Edit seeAlsoGraph.json and run config/generateSeeAlso.js -->
<!-- seealso start --> <!-- seealso start -->
## See also ## See also

View File

@@ -15,6 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { DynamicComponentResolver } from 'ng2-alfresco-core';
import { import {
AttachWidgetComponent, AttachWidgetComponent,
FormFieldModel, FormFieldModel,
@@ -22,7 +23,7 @@ import {
UnknownWidgetComponent, UnknownWidgetComponent,
UploadWidgetComponent UploadWidgetComponent
} from './../components/widgets/index'; } from './../components/widgets/index';
import { DefaultTypeResolver, FormRenderingService } from './form-rendering.service'; import { FormRenderingService } from './form-rendering.service';
describe('FormRenderingService', () => { describe('FormRenderingService', () => {
@@ -88,9 +89,9 @@ describe('FormRenderingService', () => {
expect( expect(
() => service.setComponentTypeResolver( () => service.setComponentTypeResolver(
null, 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', () => { it('should require type resolver instance to set resolver for type', () => {
@@ -106,13 +107,13 @@ describe('FormRenderingService', () => {
expect( expect(
() => service.setComponentTypeResolver( () => service.setComponentTypeResolver(
FormFieldTypes.TEXT, FormFieldTypes.TEXT,
DefaultTypeResolver.fromType(UnknownWidgetComponent) DynamicComponentResolver.fromType(UnknownWidgetComponent)
) )
).toThrowError('already mapped, use override option if you intend replacing existing mapping.'); ).toThrowError('already mapped, use override option if you intend replacing existing mapping.');
}); });
it('should override existing resolver with explicit flag', () => { it('should override existing resolver with explicit flag', () => {
let customResolver = DefaultTypeResolver.fromType(UnknownWidgetComponent); let customResolver = DynamicComponentResolver.fromType(UnknownWidgetComponent);
service.setComponentTypeResolver(FormFieldTypes.TEXT, customResolver, true); service.setComponentTypeResolver(FormFieldTypes.TEXT, customResolver, true);
expect(service.getComponentTypeResolver(FormFieldTypes.TEXT)).toBe(customResolver); expect(service.getComponentTypeResolver(FormFieldTypes.TEXT)).toBe(customResolver);
}); });

View File

@@ -16,6 +16,7 @@
*/ */
import { Injectable, Type } from '@angular/core'; import { Injectable, Type } from '@angular/core';
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from 'ng2-alfresco-core';
import { import {
AmountWidgetComponent, AmountWidgetComponent,
@@ -41,30 +42,33 @@ import {
} from './../components/widgets/index'; } from './../components/widgets/index';
@Injectable() @Injectable()
export class FormRenderingService { export class FormRenderingService extends DynamicComponentMapper {
private types: { [key: string]: ComponentTypeResolver } = { protected defaultValue: Type<{}> = UnknownWidgetComponent;
'text': DefaultTypeResolver.fromType(TextWidgetComponent), protected types: { [key: string]: DynamicComponentResolveFunction } = {
'string': DefaultTypeResolver.fromType(TextWidgetComponent), 'text': DynamicComponentResolver.fromType(TextWidgetComponent),
'integer': DefaultTypeResolver.fromType(NumberWidgetComponent), 'string': DynamicComponentResolver.fromType(TextWidgetComponent),
'multi-line-text': DefaultTypeResolver.fromType(MultilineTextWidgetComponentComponent), 'integer': DynamicComponentResolver.fromType(NumberWidgetComponent),
'boolean': DefaultTypeResolver.fromType(CheckboxWidgetComponent), 'multi-line-text': DynamicComponentResolver.fromType(MultilineTextWidgetComponentComponent),
'dropdown': DefaultTypeResolver.fromType(DropdownWidgetComponent), 'boolean': DynamicComponentResolver.fromType(CheckboxWidgetComponent),
'date': DefaultTypeResolver.fromType(DateWidgetComponent), 'dropdown': DynamicComponentResolver.fromType(DropdownWidgetComponent),
'amount': DefaultTypeResolver.fromType(AmountWidgetComponent), 'date': DynamicComponentResolver.fromType(DateWidgetComponent),
'radio-buttons': DefaultTypeResolver.fromType(RadioButtonsWidgetComponent), 'amount': DynamicComponentResolver.fromType(AmountWidgetComponent),
'hyperlink': DefaultTypeResolver.fromType(HyperlinkWidgetComponent), 'radio-buttons': DynamicComponentResolver.fromType(RadioButtonsWidgetComponent),
'readonly-text': DefaultTypeResolver.fromType(DisplayTextWidgetComponentComponent), 'hyperlink': DynamicComponentResolver.fromType(HyperlinkWidgetComponent),
'typeahead': DefaultTypeResolver.fromType(TypeaheadWidgetComponent), 'readonly-text': DynamicComponentResolver.fromType(DisplayTextWidgetComponentComponent),
'people': DefaultTypeResolver.fromType(PeopleWidgetComponent), 'typeahead': DynamicComponentResolver.fromType(TypeaheadWidgetComponent),
'functional-group': DefaultTypeResolver.fromType(FunctionalGroupWidgetComponent), 'people': DynamicComponentResolver.fromType(PeopleWidgetComponent),
'dynamic-table': DefaultTypeResolver.fromType(DynamicTableWidgetComponent), 'functional-group': DynamicComponentResolver.fromType(FunctionalGroupWidgetComponent),
'container': DefaultTypeResolver.fromType(ContainerWidgetComponent), 'dynamic-table': DynamicComponentResolver.fromType(DynamicTableWidgetComponent),
'group': DefaultTypeResolver.fromType(ContainerWidgetComponent), 'container': DynamicComponentResolver.fromType(ContainerWidgetComponent),
'document': DefaultTypeResolver.fromType(DocumentWidgetComponent) 'group': DynamicComponentResolver.fromType(ContainerWidgetComponent),
'document': DynamicComponentResolver.fromType(DocumentWidgetComponent)
}; };
constructor() { constructor() {
super();
this.types['upload'] = (field: FormFieldModel): Type<{}> => { this.types['upload'] = (field: FormFieldModel): Type<{}> => {
if (field) { if (field) {
let params = field.params; let params = field.params;
@@ -76,47 +80,4 @@ export class FormRenderingService {
return UnknownWidgetComponent; 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;
};
}
} }

View File

@@ -39,6 +39,7 @@ import { AuthGuardBpm } from './src/services/auth-guard-bpm.service';
import { AuthGuardEcm } from './src/services/auth-guard-ecm.service'; import { AuthGuardEcm } from './src/services/auth-guard-ecm.service';
import { AuthGuard } from './src/services/auth-guard.service'; import { AuthGuard } from './src/services/auth-guard.service';
import { AuthenticationService } from './src/services/authentication.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 { CommentProcessService } from './src/services/comment-process.service';
import { ContentService } from './src/services/content.service'; import { ContentService } from './src/services/content.service';
import { CookieService } from './src/services/cookie.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 { AppConfigService } from './src/services/app-config.service';
export { ThumbnailService } from './src/services/thumbnail.service'; export { ThumbnailService } from './src/services/thumbnail.service';
export { UploadService } from './src/services/upload.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 { CardViewUpdateService } from './src/services/card-view-update.service';
export { UpdateNotification } 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'; 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/folder-created.event';
export * from './src/events/file.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-textitem.model';
export * from './src/models/card-view-mapitem.model'; export * from './src/models/card-view-mapitem.model';
export * from './src/models/card-view-dateitem.model'; export * from './src/models/card-view-dateitem.model';
@@ -219,6 +223,7 @@ export function providers() {
PeopleProcessService, PeopleProcessService,
AppsProcessService, AppsProcessService,
CommentProcessService, CommentProcessService,
CardItemTypeService,
AppConfigService AppConfigService
]; ];
} }

View File

@@ -22,6 +22,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { CardViewItem } from '../../interface/card-view-item.interface'; 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 { CardViewContentProxyDirective } from './card-view-content-proxy.directive';
import { CardViewItemDispatcherComponent } from './card-view-item-dispatcher.component'; import { CardViewItemDispatcherComponent } from './card-view-item-dispatcher.component';
@@ -37,9 +38,13 @@ export class CardViewShinyCustomElementItemComponent {
describe('CardViewItemDispatcherComponent', () => { describe('CardViewItemDispatcherComponent', () => {
let fixture: ComponentFixture<CardViewItemDispatcherComponent>; let fixture: ComponentFixture<CardViewItemDispatcherComponent>;
let cardItemTypeService: CardItemTypeService;
let component: CardViewItemDispatcherComponent; let component: CardViewItemDispatcherComponent;
beforeEach(async(() => { beforeEach(async(() => {
cardItemTypeService = new CardItemTypeService();
cardItemTypeService.setComponentTypeResolver('shiny-custom-element', () => CardViewShinyCustomElementItemComponent);
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [], imports: [],
declarations: [ declarations: [
@@ -47,7 +52,7 @@ describe('CardViewItemDispatcherComponent', () => {
CardViewShinyCustomElementItemComponent, CardViewShinyCustomElementItemComponent,
CardViewContentProxyDirective CardViewContentProxyDirective
], ],
providers: [] providers: [ { provide: CardItemTypeService, useValue: cardItemTypeService } ]
}); });
// entryComponents are not supported yet on TestBed, that is why this ugly workaround: // entryComponents are not supported yet on TestBed, that is why this ugly workaround:

View File

@@ -20,10 +20,10 @@ import {
ComponentFactoryResolver, ComponentFactoryResolver,
Input, Input,
OnChanges, OnChanges,
Type,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import { CardViewItem } from '../../interface/card-view-item.interface'; 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 { CardViewContentProxyDirective } from './card-view-content-proxy.directive';
@Component({ @Component({
@@ -46,7 +46,8 @@ export class CardViewItemDispatcherComponent implements OnChanges {
public ngOnInit; public ngOnInit;
public ngDoCheck; public ngDoCheck;
constructor(private resolver: ComponentFactoryResolver) { constructor(private cardItemTypeService: CardItemTypeService,
private resolver: ComponentFactoryResolver) {
const dynamicLifecycleMethods = [ const dynamicLifecycleMethods = [
'ngOnInit', 'ngOnInit',
'ngDoCheck', 'ngDoCheck',
@@ -72,11 +73,8 @@ export class CardViewItemDispatcherComponent implements OnChanges {
} }
private loadComponent() { private loadComponent() {
const upperCamelCasedType = this.getUpperCamelCase(this.property.type), const factoryClass = this.cardItemTypeService.resolveComponentType(this.property);
className = `CardView${upperCamelCasedType}ItemComponent`;
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); const factory = this.resolver.resolveComponentFactory(factoryClass);
this.componentReference = this.content.viewContainerRef.createComponent(factory); this.componentReference = this.content.viewContainerRef.createComponent(factory);
@@ -84,11 +82,6 @@ export class CardViewItemDispatcherComponent implements OnChanges {
this.componentReference.instance.property = this.property; 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) { private proxy(methodName, ...args) {
if (this.componentReference.instance[methodName]) { if (this.componentReference.instance[methodName]) {
this.componentReference.instance[methodName].apply(this.componentReference.instance, args); this.componentReference.instance[methodName].apply(this.componentReference.instance, args);

View File

@@ -25,13 +25,14 @@
import * as moment from 'moment'; import * as moment from 'moment';
import { CardViewItem } from '../interface/card-view-item.interface'; import { CardViewItem } from '../interface/card-view-item.interface';
import { DynamicComponentModel } from '../services/dynamic-component-mapper.service';
import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model'; import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model';
export interface CardViewDateItemProperties extends CardViewItemProperties { export interface CardViewDateItemProperties extends CardViewItemProperties {
format?: string; format?: string;
} }
export class CardViewDateItemModel extends CardViewBaseItemModel implements CardViewItem { export class CardViewDateItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
type: string = 'date'; type: string = 'date';
format: string; format: string;

View File

@@ -24,9 +24,10 @@
*/ */
import { CardViewItem } from '../interface/card-view-item.interface'; import { CardViewItem } from '../interface/card-view-item.interface';
import { DynamicComponentModel } from '../services/dynamic-component-mapper.service';
import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model'; 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'; type: string = 'map';
value: Map<string, string>; value: Map<string, string>;

View File

@@ -24,12 +24,13 @@
*/ */
import { CardViewItem } from '../interface/card-view-item.interface'; import { CardViewItem } from '../interface/card-view-item.interface';
import { DynamicComponentModel } from '../services/dynamic-component-mapper.service';
import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model'; import { CardViewBaseItemModel, CardViewItemProperties } from './card-view-baseitem.model';
export interface CardViewTextItemProperties extends CardViewItemProperties { export interface CardViewTextItemProperties extends CardViewItemProperties {
multiline?: boolean; multiline?: boolean;
} }
export class CardViewTextItemModel extends CardViewBaseItemModel implements CardViewItem { export class CardViewTextItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
type: string = 'text'; type: string = 'text';
multiline: boolean; multiline: boolean;

View File

@@ -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)
};
}

View File

@@ -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;
}
}