aurelia-templating-resources
Version:
A standard set of behaviors, converters and other resources for use with the Aurelia templating library.
136 lines (118 loc) • 3.03 kB
text/typescript
import { ViewFactory, ViewSlot } from 'aurelia-templating';
/**
* For internal use only. May change without warning.
*/
export class IfCore {
/**
* @internal
*/
viewFactory: ViewFactory;
/**
* @internal
*/
viewSlot: ViewSlot;
/**
* @internal
*/
view: any;
/**
* @internal
*/
bindingContext: any;
/**
* @internal
*/
overrideContext: any;
/**
* @internal
*/
showing: boolean;
/**
* @internal
*/
cache: boolean | string;
constructor(viewFactory: ViewFactory, viewSlot: ViewSlot) {
this.viewFactory = viewFactory;
this.viewSlot = viewSlot;
this.view = null;
this.bindingContext = null;
this.overrideContext = null;
// If the child view is animated, `value` might not reflect the internal
// state anymore, so we use `showing` for that.
// Eventually, `showing` and `value` should be consistent.
this.showing = false;
this.cache = true;
}
bind(bindingContext, overrideContext) {
// Store parent bindingContext, so we can pass it down
this.bindingContext = bindingContext;
this.overrideContext = overrideContext;
}
unbind() {
if (this.view === null) {
return;
}
this.view.unbind();
// It seems to me that this code is subject to race conditions when animating.
// For example a view could be returned to the cache and reused while it's still
// attached to the DOM and animated.
if (!this.viewFactory.isCaching) {
return;
}
if (this.showing) {
this.showing = false;
this.viewSlot.remove(this.view, /*returnToCache:*/true, /*skipAnimation:*/true);
} else {
this.view.returnToCache();
}
this.view = null;
}
/**
* @internal
*/
_show() {
if (this.showing) {
// Ensures the view is bound.
// It might not be the case when the if was unbound but not detached, then rebound.
// Typical case where this happens is nested ifs
if (!this.view.isBound) {
this.view.bind(this.bindingContext, this.overrideContext);
}
return;
}
if (this.view === null) {
this.view = (this.viewFactory as any).create();
}
if (!this.view.isBound) {
this.view.bind(this.bindingContext, this.overrideContext);
}
this.showing = true;
return this.viewSlot.add(this.view); // Promise or void
}
/**
* @internal
*/
_hide() {
if (!this.showing) {
return;
}
this.showing = false;
let removed = this.viewSlot.remove(this.view); // Promise or View
if (removed instanceof Promise) {
return removed.then(() => {
this._unbindView();
});
}
this._unbindView();
}
/**
* @internal
*/
_unbindView() {
const cache = this.cache === 'false' ? false : !!this.cache;
this.view.unbind();
if (!cache) {
this.view = null;
}
}
}