@wizdm/teleport
Version:
Template teleporting
84 lines • 11.2 kB
JavaScript
import { Directive, SimpleChange, Input, Output, EventEmitter, TemplateRef, ViewContainerRef } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';
import { switchMap, delay } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
import { TeleportService } from './teleport.service';
export class PortalDirective extends NgTemplateOutlet {
constructor(teleport, host, container) {
super(container);
this.teleport = teleport;
this.host = host;
this.name$ = new BehaviorSubject('');
this.firstChange = true;
/** The actual template in use. NOTE for this event to bind correclty the directive must be used in its de-sugared form */
this.template = new EventEmitter();
/** True then the portal is active */
this.active = new EventEmitter();
/** Optional data passed along from the TeleportDirective back to the Portal */
this.data = new EventEmitter();
// Builds the template observable
this.sub = this.name$.pipe(
// Beams the content with the given name
switchMap(name => this.teleport.beam(name)),
// Wait the next round to avoid expressionChangedAfterItHasBeenChecked() exception
delay(0)).subscribe(payload => this.changeTemplate(payload || {}));
}
/** The portal name */
set name(name) { this.name$.next(name); }
changeTemplate({ template, data }) {
// Emits the new optional data, if any
if (typeof (data) !== undefined) {
this.data.emit(data);
}
/** Skips on no template changes */
if (template === this.ngTemplateOutlet) {
return;
}
// Creates a simple change object
const ngTemplateOutlet = new SimpleChange(this.ngTemplateOutlet, template || this.host, this.firstChange);
// Updates the parent's template variable accordingly
this.ngTemplateOutlet = ngTemplateOutlet.currentValue;
// Tracks for the first change
this.firstChange = false;
// Forces the change to occur
super.ngOnChanges({ ngTemplateOutlet });
// Emits the new template
this.template.emit(this.ngTemplateOutlet);
// Emits true whenever the template isn't the host one
this.active.emit(this.ngTemplateOutlet !== this.host);
}
// Intercepts the input changes
ngOnChanges(changes) {
// Gets rid of the name's SimpleChange object
if (changes.name) {
delete changes.name;
}
// Skips when no changes remains
if (Object.keys(changes).length === 0) {
return;
}
// Lets the context changes go through
super.ngOnChanges(changes);
}
// Disposes of the subscription on deletion
ngOnDestroy() { this.sub.unsubscribe(); }
}
PortalDirective.decorators = [
{ type: Directive, args: [{
selector: 'ng-template[wmPortal]',
exportAs: 'wmPortal'
},] }
];
PortalDirective.ctorParameters = () => [
{ type: TeleportService },
{ type: TemplateRef },
{ type: ViewContainerRef }
];
PortalDirective.propDecorators = {
name: [{ type: Input, args: ['wmPortal',] }],
ngTemplateOutletContext: [{ type: Input, args: ['wmPortalContext',] }],
template: [{ type: Output, args: ['wmPortalTemplate',] }],
active: [{ type: Output, args: ['wmPortalActive',] }],
data: [{ type: Output, args: ['wmPortalData',] }]
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9ydGFsLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RlbGVwb3J0L3NyYy9saWIvcG9ydGFsLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUF1QyxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pKLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEQsT0FBTyxFQUFnQixlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQU10RSxNQUFNLE9BQU8sZUFBZ0IsU0FBUSxnQkFBZ0I7SUFxQm5ELFlBQW9CLFFBQXlCLEVBQVUsSUFBOEIsRUFBRSxTQUEyQjtRQUNoSCxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFEQyxhQUFRLEdBQVIsUUFBUSxDQUFpQjtRQUFVLFNBQUksR0FBSixJQUFJLENBQTBCO1FBbkI3RSxVQUFLLEdBQUcsSUFBSSxlQUFlLENBQVMsRUFBRSxDQUFDLENBQUM7UUFDeEMsZ0JBQVcsR0FBWSxJQUFJLENBQUM7UUFTcEMsMEhBQTBIO1FBQzlGLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBNEIsQ0FBQztRQUVwRixzQ0FBc0M7UUFDWixXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUUvRCwrRUFBK0U7UUFDdkQsU0FBSSxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7UUFLckQsaUNBQWlDO1FBQ2pDLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJO1FBRXhCLHdDQUF3QztRQUN4QyxTQUFTLENBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBRTtRQUU3QyxrRkFBa0Y7UUFDbEYsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUVULENBQUMsU0FBUyxDQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLElBQUksRUFBcUIsQ0FBQyxDQUFFLENBQUM7SUFDbEYsQ0FBQztJQTVCRCxzQkFBc0I7SUFDdEIsSUFBdUIsSUFBSSxDQUFDLElBQVksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUE2QjVELGNBQWMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQW1CO1FBRXhELHNDQUFzQztRQUN0QyxJQUFHLE9BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxTQUFTLEVBQUU7WUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUFFO1FBRXhELG1DQUFtQztRQUNuQyxJQUFHLFFBQVEsS0FBSyxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFBRSxPQUFPO1NBQUU7UUFFbEQsaUNBQWlDO1FBQ2pDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLFFBQVEsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUxRyxxREFBcUQ7UUFDckQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLGdCQUFnQixDQUFDLFlBQVksQ0FBQztRQUV0RCw4QkFBOEI7UUFDOUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFFekIsNkJBQTZCO1FBQzdCLEtBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7UUFFeEMseUJBQXlCO1FBQ3pCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRTFDLHNEQUFzRDtRQUN0RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCwrQkFBK0I7SUFDL0IsV0FBVyxDQUFDLE9BQXNCO1FBRWhDLDZDQUE2QztRQUM3QyxJQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUU7WUFBRSxPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUM7U0FBRTtRQUV6QyxnQ0FBZ0M7UUFDaEMsSUFBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFBRSxPQUFPO1NBQUU7UUFFakQsc0NBQXNDO1FBQ3RDLEtBQUssQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELDJDQUEyQztJQUMzQyxXQUFXLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7OztZQWpGMUMsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSx1QkFBdUI7Z0JBQ2pDLFFBQVEsRUFBRSxVQUFVO2FBQ3JCOzs7WUFMUSxlQUFlO1lBSjRFLFdBQVc7WUFBRSxnQkFBZ0I7OzttQkFpQjlILEtBQUssU0FBQyxVQUFVO3NDQUdoQixLQUFLLFNBQUMsaUJBQWlCO3VCQUd2QixNQUFNLFNBQUMsa0JBQWtCO3FCQUd6QixNQUFNLFNBQUMsZ0JBQWdCO21CQUd2QixNQUFNLFNBQUMsY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgT25EZXN0cm95LCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMsIFNpbXBsZUNoYW5nZSwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBUZW1wbGF0ZVJlZiwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmdUZW1wbGF0ZU91dGxldCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIGRlbGF5IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRlbGVwb3J0U2VydmljZSwgVGVsZXBvcnRQYXlsb2FkIH0gZnJvbSAnLi90ZWxlcG9ydC5zZXJ2aWNlJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnbmctdGVtcGxhdGVbd21Qb3J0YWxdJyxcbiAgZXhwb3J0QXM6ICd3bVBvcnRhbCdcbn0pXG5leHBvcnQgY2xhc3MgUG9ydGFsRGlyZWN0aXZlIGV4dGVuZHMgTmdUZW1wbGF0ZU91dGxldCBpbXBsZW1lbnRzIE9uRGVzdHJveSwgT25DaGFuZ2VzIHtcblxuICBwcml2YXRlIG5hbWUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgcHJpdmF0ZSBmaXJzdENoYW5nZTogYm9vbGVhbiA9IHRydWU7XG4gIHByaXZhdGUgc3ViOiBTdWJzY3JpcHRpb247XG5cbiAgLyoqIFRoZSBwb3J0YWwgbmFtZSAqL1xuICBASW5wdXQoJ3dtUG9ydGFsJykgc2V0IG5hbWUobmFtZTogc3RyaW5nKSB7IHRoaXMubmFtZSQubmV4dChuYW1lKTsgfVxuXG4gIC8qKiBUaGUgcG9ydGFsIGNvbnRleHQgKi9cbiAgQElucHV0KCd3bVBvcnRhbENvbnRleHQnKSBuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dDogT2JqZWN0fG51bGw7XG5cbiAgLyoqIFRoZSBhY3R1YWwgdGVtcGxhdGUgaW4gdXNlLiBOT1RFIGZvciB0aGlzIGV2ZW50IHRvIGJpbmQgY29ycmVjbHR5IHRoZSBkaXJlY3RpdmUgbXVzdCBiZSB1c2VkIGluIGl0cyBkZS1zdWdhcmVkIGZvcm0gKi9cbiAgQE91dHB1dCgnd21Qb3J0YWxUZW1wbGF0ZScpIHRlbXBsYXRlID0gbmV3IEV2ZW50RW1pdHRlcjxUZW1wbGF0ZVJlZjxPYmplY3R8bnVsbD4+KCk7XG5cbiAgLyoqIFRydWUgdGhlbiB0aGUgcG9ydGFsIGlzIGFjdGl2ZSAgKi9cbiAgQE91dHB1dCgnd21Qb3J0YWxBY3RpdmUnKSBhY3RpdmUgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgLyoqIE9wdGlvbmFsIGRhdGEgcGFzc2VkIGFsb25nIGZyb20gdGhlIFRlbGVwb3J0RGlyZWN0aXZlIGJhY2sgdG8gdGhlIFBvcnRhbCAqL1xuICBAT3V0cHV0KCd3bVBvcnRhbERhdGEnKSBkYXRhID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSB0ZWxlcG9ydDogVGVsZXBvcnRTZXJ2aWNlLCBwcml2YXRlIGhvc3Q6IFRlbXBsYXRlUmVmPE9iamVjdHxudWxsPiwgY29udGFpbmVyOiBWaWV3Q29udGFpbmVyUmVmKSB7IFxuICAgIHN1cGVyKGNvbnRhaW5lcik7IFxuXG4gICAgLy8gQnVpbGRzIHRoZSB0ZW1wbGF0ZSBvYnNlcnZhYmxlXG4gICAgdGhpcy5zdWIgPSB0aGlzLm5hbWUkLnBpcGUoIFxuXG4gICAgICAvLyBCZWFtcyB0aGUgY29udGVudCB3aXRoIHRoZSBnaXZlbiBuYW1lXG4gICAgICBzd2l0Y2hNYXAoIG5hbWUgPT4gdGhpcy50ZWxlcG9ydC5iZWFtKG5hbWUpICksXG5cbiAgICAgIC8vIFdhaXQgdGhlIG5leHQgcm91bmQgdG8gYXZvaWQgZXhwcmVzc2lvbkNoYW5nZWRBZnRlckl0SGFzQmVlbkNoZWNrZWQoKSBleGNlcHRpb25cbiAgICAgIGRlbGF5KDApXG4gXG4gICAgKS5zdWJzY3JpYmUoIHBheWxvYWQgPT4gdGhpcy5jaGFuZ2VUZW1wbGF0ZShwYXlsb2FkIHx8IHt9IGFzIFRlbGVwb3J0UGF5bG9hZCkgKTtcbiAgfVxuXG4gIHByaXZhdGUgY2hhbmdlVGVtcGxhdGUoeyB0ZW1wbGF0ZSwgZGF0YSB9OiBUZWxlcG9ydFBheWxvYWQpIHtcblxuICAgIC8vIEVtaXRzIHRoZSBuZXcgb3B0aW9uYWwgZGF0YSwgaWYgYW55XG4gICAgaWYodHlwZW9mKGRhdGEpICE9PSB1bmRlZmluZWQpIHsgdGhpcy5kYXRhLmVtaXQoZGF0YSk7IH1cblxuICAgIC8qKiBTa2lwcyBvbiBubyB0ZW1wbGF0ZSBjaGFuZ2VzICovXG4gICAgaWYodGVtcGxhdGUgPT09IHRoaXMubmdUZW1wbGF0ZU91dGxldCkgeyByZXR1cm47IH1cblxuICAgIC8vIENyZWF0ZXMgYSBzaW1wbGUgY2hhbmdlIG9iamVjdFxuICAgIGNvbnN0IG5nVGVtcGxhdGVPdXRsZXQgPSBuZXcgU2ltcGxlQ2hhbmdlKHRoaXMubmdUZW1wbGF0ZU91dGxldCwgdGVtcGxhdGUgfHwgdGhpcy5ob3N0LCB0aGlzLmZpcnN0Q2hhbmdlKTtcblxuICAgIC8vIFVwZGF0ZXMgdGhlIHBhcmVudCdzIHRlbXBsYXRlIHZhcmlhYmxlIGFjY29yZGluZ2x5XG4gICAgdGhpcy5uZ1RlbXBsYXRlT3V0bGV0ID0gbmdUZW1wbGF0ZU91dGxldC5jdXJyZW50VmFsdWU7XG4gICAgXG4gICAgLy8gVHJhY2tzIGZvciB0aGUgZmlyc3QgY2hhbmdlXG4gICAgdGhpcy5maXJzdENoYW5nZSA9IGZhbHNlO1xuICAgIFxuICAgIC8vIEZvcmNlcyB0aGUgY2hhbmdlIHRvIG9jY3VyXG4gICAgc3VwZXIubmdPbkNoYW5nZXMoeyBuZ1RlbXBsYXRlT3V0bGV0IH0pO1xuXG4gICAgLy8gRW1pdHMgdGhlIG5ldyB0ZW1wbGF0ZVxuICAgIHRoaXMudGVtcGxhdGUuZW1pdCh0aGlzLm5nVGVtcGxhdGVPdXRsZXQpO1xuXG4gICAgLy8gRW1pdHMgdHJ1ZSB3aGVuZXZlciB0aGUgdGVtcGxhdGUgaXNuJ3QgdGhlIGhvc3Qgb25lXG4gICAgdGhpcy5hY3RpdmUuZW1pdCh0aGlzLm5nVGVtcGxhdGVPdXRsZXQgIT09IHRoaXMuaG9zdCk7XG4gIH1cblxuICAvLyBJbnRlcmNlcHRzIHRoZSBpbnB1dCBjaGFuZ2VzXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBcbiAgICAvLyBHZXRzIHJpZCBvZiB0aGUgbmFtZSdzIFNpbXBsZUNoYW5nZSBvYmplY3RcbiAgICBpZihjaGFuZ2VzLm5hbWUpIHsgZGVsZXRlIGNoYW5nZXMubmFtZTsgfVxuICAgIFxuICAgIC8vIFNraXBzIHdoZW4gbm8gY2hhbmdlcyByZW1haW5zXG4gICAgaWYoT2JqZWN0LmtleXMoY2hhbmdlcykubGVuZ3RoID09PSAwKSB7IHJldHVybjsgfVxuICAgIFxuICAgIC8vIExldHMgdGhlIGNvbnRleHQgY2hhbmdlcyBnbyB0aHJvdWdoXG4gICAgc3VwZXIubmdPbkNoYW5nZXMoY2hhbmdlcyk7XG4gIH1cblxuICAvLyBEaXNwb3NlcyBvZiB0aGUgc3Vic2NyaXB0aW9uIG9uIGRlbGV0aW9uXG4gIG5nT25EZXN0cm95KCkgeyB0aGlzLnN1Yi51bnN1YnNjcmliZSgpOyB9XG59Il19