Browse Source

feat(core): create replaceable-template directive

#2404
pull/2522/head
mehmet-erim 7 years ago
parent
commit
57403b86d1
  1. 16
      npm/ng-packs/packages/core/src/lib/core.module.ts
  2. 2
      npm/ng-packs/packages/core/src/lib/directives/index.ts
  3. 118
      npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts

16
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -31,6 +31,8 @@ import { getInitialData, localeInitializer } from './utils/initial-utils';
import './utils/date-extensions';
import { ReplaceableRouteContainerComponent } from './components/replaceable-route-container.component';
import { ReplaceableComponentsState } from './states/replaceable-components.state';
import { InitDirective } from './directives/init.directive';
import { ReplaceableTemplateDirective } from './directives/replaceable-template.directive';
@NgModule({
imports: [
@ -46,6 +48,7 @@ import { ReplaceableComponentsState } from './states/replaceable-components.stat
],
declarations: [
ReplaceableRouteContainerComponent,
ReplaceableTemplateContainerComponent,
RouterOutletComponent,
DynamicLayoutComponent,
AutofocusDirective,
@ -54,6 +57,7 @@ import { ReplaceableComponentsState } from './states/replaceable-components.stat
FormSubmitDirective,
LocalizationPipe,
SortPipe,
InitDirective,
PermissionDirective,
VisibilityDirective,
InputEventDebounceDirective,
@ -68,19 +72,21 @@ import { ReplaceableComponentsState } from './states/replaceable-components.stat
RouterModule,
RouterOutletComponent,
DynamicLayoutComponent,
AbstractNgModelComponent,
ReplaceableRouteContainerComponent,
AutofocusDirective,
EllipsisDirective,
ForDirective,
FormSubmitDirective,
LocalizationPipe,
SortPipe,
InitDirective,
PermissionDirective,
VisibilityDirective,
InputEventDebounceDirective,
LocalizationPipe,
ReplaceableTemplateDirective,
StopPropagationDirective,
AbstractNgModelComponent,
ReplaceableRouteContainerComponent,
LocalizationPipe,
SortPipe,
LocalizationPipe,
],
providers: [LocalizationPipe],
entryComponents: [

2
npm/ng-packs/packages/core/src/lib/directives/index.ts

@ -2,5 +2,7 @@ export * from './autofocus.directive';
export * from './ellipsis.directive';
export * from './for.directive';
export * from './form-submit.directive';
export * from './init.directive';
export * from './permission.directive';
export * from './replaceable-template.directive';
export * from './visibility.directive';

118
npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts

@ -0,0 +1,118 @@
import {
ComponentFactoryResolver,
Directive,
Injector,
Input,
OnDestroy,
OnInit,
TemplateRef,
Type,
ViewContainerRef,
SimpleChanges,
} from '@angular/core';
import { Store } from '@ngxs/store';
import compare from 'just-compare';
import { filter } from 'rxjs/operators';
import { ReplaceableComponents } from '../models/replaceable-components';
import { ReplaceableComponentsState } from '../states/replaceable-components.state';
import { takeUntilDestroy } from '../utils/rxjs-utils';
@Directive({ selector: '[abpReplaceableTemplate]' })
export class ReplaceableTemplateDirective implements OnInit, OnDestroy {
private context = {};
@Input('abpReplaceableTemplate')
data: { inputs: any; outputs: any; componentKey: string };
providedData = { inputs: {}, outputs: {} } as { inputs: any; outputs: any; componentKey: string };
externalComponent: Type<any> = null; // externalComponent must equal to null
defaultComponentRef: any;
constructor(
private injector: Injector,
private templateRef: TemplateRef<any>,
private cfRes: ComponentFactoryResolver,
private vcRef: ViewContainerRef,
private store: Store,
) {
this.context = {
initTemplate: ref => {
this.defaultComponentRef = ref;
this.setDefaultComponentInputs();
setTimeout(() => {
ref.providerKey = 'admin';
ref.visible = true;
}, 5000);
},
};
}
ngOnInit() {
this.store
.select(ReplaceableComponentsState.getComponent(this.data.componentKey))
.pipe(
filter(
(res = {} as ReplaceableComponents.ReplaceableComponent) =>
!compare(res.component, this.externalComponent),
),
takeUntilDestroy(this),
)
.subscribe((res = {} as ReplaceableComponents.ReplaceableComponent) => {
this.vcRef.clear();
this.externalComponent = res.component;
if (res.component) {
this.setProvidedData();
const customInjector = Injector.create({
providers: [{ provide: 'REPLACEABLE_DATA', useValue: this.providedData }],
parent: this.injector,
});
this.vcRef.createComponent(
this.cfRes.resolveComponentFactory(res.component),
0,
customInjector,
);
} else {
this.vcRef.createEmbeddedView(this.templateRef, this.context);
}
});
}
ngOnChanges(changes: SimpleChanges) {
console.log(changes);
}
ngOnDestroy() {}
setDefaultComponentInputs() {
if (!this.defaultComponentRef) return;
}
setProvidedData() {
Object.defineProperties(this.providedData.inputs, {
...Object.keys(this.data.inputs).reduce(
(acc, key) => ({
...acc,
[key]: {
enumerable: true,
configurable: true,
get: () => this.data.inputs[key].value,
...(this.data.inputs[key].twoWay && {
set: newValue => {
this.data.inputs[key].value = newValue;
this.data.outputs[`${key}Change`](newValue);
},
}),
},
}),
{},
),
});
this.providedData.outputs = this.data.outputs;
console.warn(this.providedData);
}
}
Loading…
Cancel
Save