import { Properties } from '../../decorators/properties.decorator';
import { BaseComponent } from '../base.component';
import { LifeCycle } from '../lifecycle.enum';
import { uuidv4 } from '../../code/utils';
import { Events } from '../../decorators';
/**
* This component allows to create an outlet, that has no vivible DOM node.
* A comment node is being replaced by the actual node delivered from router.
* That's an option onw might need in case of weak CSS that changes its behavior if a DIV element or other regular HTML element appears.
*
* In the render method add the element as a regular component.
*
* This component fires an event, `mutation`, that indicates the content has been changed by the router infrastructure.
*
* ``
*
* As with any other outlet you can add a name by using the *name* parameter. That is an observed attribute.
*
* ``
*
* @event mutation Custom event that has a {@link MutationRecord} in the detail property.
*
*/
@Properties<{ name?: string }>({ name: '' })
@Events(['mutation'])
export class NOutletComponent extends BaseComponent<{ name: '' }> {
constructor() {
super();
}
private observer: MutationObserver;
private outletId: string;
render() {
this.outletId = uuidv4();
return ``;
}
lifeCycle(state: LifeCycle) {
if (state === LifeCycle.Load) {
const tw = document.createTreeWalker(this, NodeFilter.SHOW_COMMENT, null, null);
let watchTarget: Comment = null;
while (watchTarget = tw.nextNode() as Comment) {
if (watchTarget.data.indexOf('OUTLET') === 0) {
const targetContainer = watchTarget.parentElement;
this.observer = new MutationObserver((mutations) => {
// a router has added an element and removed the comment
mutations.forEach((mutation) => {
if (mutation.target === this) {
this.dispatch('mutation', {
bubbles: true,
cancelable: false,
detail: mutation
});
}
});
// let's conserve this information and re-add
});
this.observer.observe(targetContainer, {
attributes: false,
childList: true,
characterData: true,
subtree: true
});
}
}
}
if (state === LifeCycle.Disconnect && this.observer) {
this.observer.disconnect();
}
}
}