@surface/custom-element
Version:
Provides support of directives and data binding on custom elements.
53 lines (52 loc) • 2.29 kB
JavaScript
import { CancellationTokenSource } from "@surface/core";
import { tryEvaluateKeyExpressionByTraceable, tryObserveByObservable, tryObserveKeyByObservable, } from "../common.js";
import TemplateMetadata from "../metadata/template-metadata.js";
import { scheduler } from "../singletons.js";
export default class InjectDirective {
constructor(template, descriptor, context) {
this.cancellationTokenSource = new CancellationTokenSource();
this.disposed = false;
this.key = "";
this.task = () => {
this.disposeCurrentInjection();
this.key = `${tryEvaluateKeyExpressionByTraceable(this.context.scope, this.descriptor)}`;
const injectionContext = {
customDirectives: this.context.directives,
descriptor: this.descriptor,
host: this.context.host,
parentNode: this.context.parentNode,
scope: this.context.scope,
template: this.template,
};
this.metadata.injections.set(this.key, injectionContext);
const action = this.metadata.placeholders.get(this.key);
if (action) {
action(injectionContext);
}
};
this.template = template;
this.descriptor = descriptor;
this.context = context;
this.metadata = TemplateMetadata.from(context.parentNode);
template.remove();
const listener = () => void scheduler.enqueue(this.task, "normal", this.cancellationTokenSource.token);
this.keySubscription = tryObserveKeyByObservable(context.scope, descriptor, listener, true);
this.subscription = tryObserveByObservable(context.scope, descriptor, listener, true);
this.task();
}
disposeCurrentInjection() {
if (this.key) {
this.metadata.injections.delete(this.key);
this.metadata.defaults.get(this.key)?.();
}
}
dispose() {
if (!this.disposed) {
this.cancellationTokenSource.cancel();
this.disposeCurrentInjection();
this.keySubscription.unsubscribe();
this.subscription.unsubscribe();
this.disposed = true;
}
}
}