mirror of https://github.com/abpframework/abp.git
3 changed files with 131 additions and 5 deletions
@ -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…
Reference in new issue