first-npm-package-nicule
Version:
This isi first npm package
128 lines (105 loc) • 4.27 kB
text/typescript
import { ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive,
Injector, Input, OnChanges, SimpleChanges, Type, ViewContainerRef } from '@angular/core';
import { NgForm } from '@angular/forms';
import { HypermediaField, LabelingService } from 'first-npm-package-nicule/core';
import { BaseInputComponent } from '../classes';
import { InputComponentResolver } from '../services';
import { HypermediaForm } from '../components';
export class InputDirective implements OnChanges {
private componentFactory: ComponentFactory<BaseInputComponent>;
private inputSettings: any = {};
private componentRef: ComponentRef<BaseInputComponent>;
private isCreated = false;
private field: HypermediaField;
set hmInputOfSettings(settings: any) {
if (settings) {
this.inputSettings = settings;
if (this.componentRef && this.componentRef.changeDetectorRef) {
this.componentRef.instance.settings = settings;
}
}
}
set hmInputOf(field: HypermediaField) {
if (field) {
this.field = field;
}
}
constructor(private viewContainer: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver,
private labelingService: LabelingService,
private injector: Injector,
private hmForm: HypermediaForm,
private inputComponentResolver: InputComponentResolver
) { }
ngOnChanges(changes: SimpleChanges): void {
if ('hmInputOf' in changes) {
this.onFieldChange(changes.hmInputOf.previousValue, changes.hmInputOf.currentValue);
}
}
onFieldChange(oldField, newField): void {
let componentType: Type<any>;
let reRender = false;
if (!this.field && !this.isCreated) {
return;
}
if ((!this.isCreated && !this.componentFactory) ||
oldField.name !== newField.name ||
oldField.type !== newField.type) {
componentType = this.inputComponentResolver.resolve(newField);
const newFactory = this.componentFactoryResolver.resolveComponentFactory(componentType);
reRender = newFactory !== this.componentFactory;
this.componentFactory = newFactory;
}
if (this.isCreated && reRender) {
this.delete();
}
if (newField && !this.isCreated) {
this.create();
} else if (newField && this.isCreated) {
this.update();
} else {
this.delete();
}
if (newField && !this.isCreated) {
this.create();
} else if (newField && this.isCreated) {
this.update();
} else {
this.delete();
}
}
delete(): void {
this.viewContainer.clear();
this.componentRef.destroy();
delete this.componentRef;
this.isCreated = false;
}
update(): void {
this.componentRef.instance.field = this.field;
this.componentRef.instance.labelingService = this.labelingService;
this.componentRef.instance.settings = { ...this.componentRef.instance.settings, ...this.inputSettings };
this.componentRef.changeDetectorRef.detectChanges();
this.componentRef.instance['onSettingsChanged']();
}
create(): void {
let injector = this.injector;
const parentInjector = this.injector;
if (this.hmForm && this.hmForm.ngForm) {
injector = {
// Force injector to resolve form as the settings form
get: (token, notFoundValue): any => {
if (token === NgForm) {
return this.hmForm.ngForm;
}
return parentInjector.get(token, notFoundValue);
}
};
}
this.componentRef = this.viewContainer.createComponent(this.componentFactory, 0, injector);
this.isCreated = true;
this.update();
}
}