2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
19 * Modifications copyright (c) 2018 Nokia
20 * ================================================================================
23 import * as _ from "lodash";
24 import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactoryResolver } from '@angular/core'
25 import {ValidationConfiguration, PropertyFEModel} from "app/models";
26 import {IUiElementChangeEvent} from "../form-components/ui-element-base.component";
27 import {UiElementInputComponent} from "../form-components/input/ui-element-input.component";
28 import {UiElementPopoverInputComponent} from "../form-components/popover-input/ui-element-popover-input.component";
29 import {UiElementIntegerInputComponent} from "../form-components/integer-input/ui-element-integer-input.component";
30 import {UiElementDropDownComponent, DropdownValue} from "../form-components/dropdown/ui-element-dropdown.component";
31 import {PROPERTY_DATA} from "../../../../utils/constants";
33 enum DynamicElementComponentCreatorIdentifier {
45 selector: 'dynamic-element',
46 // Span - if constraints not empty
47 template: `<div #target></div>`,
48 styleUrls: ['./dynamic-element.component.less'],
50 UiElementInputComponent,
51 UiElementDropDownComponent,
52 UiElementPopoverInputComponent,
53 UiElementIntegerInputComponent
56 export class DynamicElementComponent {
58 @ViewChild('target', { read: ViewContainerRef }) target: any;
60 @Input() childType: any;
61 @Input() name: string;
62 @Input() testId: string;
63 @Input() readonly:boolean;
64 @Input() constraints: Array<any>;
65 @Input() path:string;//optional param. used only for for subnetpoolid type
66 @Input() declared:boolean;
69 @Output() valueChange: EventEmitter<any> = new EventEmitter<any>();
70 @Output('elementChanged') emitter: EventEmitter<IUiElementChangeEvent> = new EventEmitter<IUiElementChangeEvent>();
72 cmpRef: ComponentRef<any>;
73 private isViewInitialized: boolean = false;
74 private elementCreatorIdentifier: DynamicElementComponentCreatorIdentifier;
75 validation = ValidationConfiguration.validation;
79 private componentFactoryResolver: ComponentFactoryResolver,
80 private compiler: Compiler,
81 private el: ElementRef) {
87 if (!this.isViewInitialized) {
91 // Factory to create component based on type or other property attributes.
92 const prevElementCreatorIdentifier: DynamicElementComponentCreatorIdentifier = this.elementCreatorIdentifier;
94 case this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1:
95 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.SUBNETPOOLID;
97 case this.getValidValues() !== undefined && this.getValidValues() !== null:
98 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.ENUM;
100 case this.type === 'integer':
101 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.INTEGER;
103 case this.type === 'float':
104 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.FLOAT;
106 case PROPERTY_DATA.SCALAR_TYPES.indexOf(this.type) > -1:
107 case this.type === 'string':
108 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.STRING;
110 case this.type === 'boolean':
111 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.BOOLEAN;
113 case this.type === 'map':
114 this.createElementCreatorIdentifierForChild();
117 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.DEFAULT;
120 // In case the dynamic element creator is changed, then destroy old and build new.
121 if (this.declared || this.elementCreatorIdentifier !== prevElementCreatorIdentifier) {
123 this.cmpRef.destroy();
125 this.createComponentByIdentifier();
128 // Update attributes in base element class
130 this.cmpRef.instance.name = this.name;
131 this.cmpRef.instance.type = this.type;
132 this.cmpRef.instance.testId = this.testId;
133 this.cmpRef.instance.value = this.value;
134 this.cmpRef.instance.readonly = this.readonly;
138 createElementCreatorIdentifierForChild():void{
139 switch(this.childType) {
141 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.INTEGER;
144 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.FLOAT;
147 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.STRING;
150 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.BOOLEAN;
153 this.elementCreatorIdentifier = DynamicElementComponentCreatorIdentifier.DEFAULT;
157 createComponentByIdentifier() {
158 // if(!this.constraints || this.declared){
159 switch(this.elementCreatorIdentifier) {
160 case DynamicElementComponentCreatorIdentifier.SUBNETPOOLID:
161 if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name
162 let pathArray = this.path.split("#");
163 this.name = pathArray[pathArray.length - 2];
165 this.createComponent(UiElementPopoverInputComponent);
167 case DynamicElementComponentCreatorIdentifier.ENUM:
168 this.createComponent(UiElementDropDownComponent);
169 let validVals:Array<DropdownValue> = [...this.getValidValues()].map(val => new DropdownValue(val, val));
170 if (this.type === 'float' || this.type === 'integer') {
171 this.value = this.value && Number(this.value);
174 (val) => new DropdownValue(Number(val.value), val.value)
177 this.cmpRef.instance.values = validVals;
179 case DynamicElementComponentCreatorIdentifier.INTEGER:
180 this.createComponent(UiElementIntegerInputComponent);
181 this.cmpRef.instance.pattern = this.validation.validationPatterns.integer;
184 case DynamicElementComponentCreatorIdentifier.FLOAT:
185 this.createComponent(UiElementIntegerInputComponent);
186 this.cmpRef.instance.pattern = /^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/.source;
189 case DynamicElementComponentCreatorIdentifier.STRING:
190 this.createComponent(UiElementInputComponent);
193 case DynamicElementComponentCreatorIdentifier.BOOLEAN:
194 this.createComponent(UiElementDropDownComponent);
196 // Build drop down values
198 tmp.push(new DropdownValue(true,'TRUE'));
199 tmp.push(new DropdownValue(false,'FALSE'));
200 this.cmpRef.instance.values = tmp;
202 if(typeof this.value === 'string'){
203 this.value = JSON.parse(this.value);
210 case DynamicElementComponentCreatorIdentifier.DEFAULT:
212 this.createComponent(UiElementInputComponent);
213 console.log("ERROR: No ui-models component to handle type: " + this.type);
216 // //There are consraints
219 // this.createComponent(UiElementDropDownComponent);
221 // // Build drop down values
223 // this.constraints.forEach( (element) => {
224 // items.push(new DropdownValue(element,element));
227 // items.push(new DropdownValue(this.value,this.value, true, true));
228 // this.cmpRef.instance.values = items;
234 // Subscribe to change event of of ui-models-element-basic and fire event to change the value
235 this.cmpRef.instance.baseEmitter.subscribe((event) => { this.emitter.emit(event); });
236 this.cmpRef.instance.valueChange.subscribe((event) => { this.valueChange.emit(event); });
239 getValidValues(): Array<string> {
241 _.forEach(this.constraints, constraint => {
242 validVals = validVals || constraint.validValues;
247 createComponent(ComponentToCreate:any):void {
248 let factory = this.componentFactoryResolver.resolveComponentFactory(ComponentToCreate);
249 this.cmpRef = this.target.createComponent(factory);
253 this.updateComponent();
256 ngAfterContentInit() {
257 this.isViewInitialized = true;
258 this.updateComponent();
263 this.cmpRef.destroy();