fix(animations): use a lightweight renderer for non-animation components (#17003)
This reverts commit c0981b8e13
.
This commit is contained in:
parent
cd5bc64658
commit
d108479d84
|
@ -48,8 +48,11 @@ export class AnimationEngine {
|
||||||
trigger = buildTrigger(name, ast);
|
trigger = buildTrigger(name, ast);
|
||||||
this._triggerCache[cacheKey] = trigger;
|
this._triggerCache[cacheKey] = trigger;
|
||||||
}
|
}
|
||||||
|
this._transitionEngine.registerTrigger(namespaceId, name, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
this._transitionEngine.register(namespaceId, hostElement, name, trigger);
|
register(namespaceId: string, hostElement: any) {
|
||||||
|
this._transitionEngine.register(namespaceId, hostElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(namespaceId: string, context: any) {
|
destroy(namespaceId: string, context: any) {
|
||||||
|
@ -86,7 +89,7 @@ export class AnimationEngine {
|
||||||
return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);
|
return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
flush(countId: number = -1): void { this._transitionEngine.flush(countId); }
|
flush(microtaskId: number = -1): void { this._transitionEngine.flush(microtaskId); }
|
||||||
|
|
||||||
get players(): AnimationPlayer[] {
|
get players(): AnimationPlayer[] {
|
||||||
return (this._transitionEngine.players as AnimationPlayer[])
|
return (this._transitionEngine.players as AnimationPlayer[])
|
||||||
|
|
|
@ -13,12 +13,13 @@ import {AnimationTransitionInstruction} from '../dsl/animation_transition_instru
|
||||||
import {AnimationTrigger} from '../dsl/animation_trigger';
|
import {AnimationTrigger} from '../dsl/animation_trigger';
|
||||||
import {ElementInstructionMap} from '../dsl/element_instruction_map';
|
import {ElementInstructionMap} from '../dsl/element_instruction_map';
|
||||||
import {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';
|
import {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';
|
||||||
import {ENTER_CLASSNAME, LEAVE_CLASSNAME, LEAVE_SELECTOR, NG_ANIMATING_CLASSNAME, NG_TRIGGER_CLASSNAME, NG_TRIGGER_SELECTOR, copyObj, eraseStyles, iteratorToArray, setStyles} from '../util';
|
import {ENTER_CLASSNAME, LEAVE_CLASSNAME, LEAVE_SELECTOR, NG_ANIMATING_CLASSNAME, NG_TRIGGER_CLASSNAME, NG_TRIGGER_SELECTOR, copyObj, eraseStyles, setStyles} from '../util';
|
||||||
|
|
||||||
import {AnimationDriver} from './animation_driver';
|
import {AnimationDriver} from './animation_driver';
|
||||||
import {getOrSetAsInMap, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, optimizeGroupPlayer} from './shared';
|
import {getOrSetAsInMap, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, optimizeGroupPlayer} from './shared';
|
||||||
|
|
||||||
const EMPTY_PLAYER_ARRAY: AnimationPlayer[] = [];
|
const EMPTY_PLAYER_ARRAY: AnimationPlayer[] = [];
|
||||||
|
const ANIMATE_EPOCH_ATTR = 'ng-animate-id';
|
||||||
|
|
||||||
interface TriggerListener {
|
interface TriggerListener {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -255,7 +256,7 @@ export class AnimationTransitionNamespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _destroyInnerNodes(rootElement: any, context: any, animate: boolean = false) {
|
private _destroyInnerNodes(rootElement: any, context: any, animate: boolean = false) {
|
||||||
listToArray(this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true)).forEach(elm => {
|
this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true).forEach(elm => {
|
||||||
if (animate && containsClass(elm, this._hostClassName)) {
|
if (animate && containsClass(elm, this._hostClassName)) {
|
||||||
const innerNs = this._engine.namespacesByHostElement.get(elm);
|
const innerNs = this._engine.namespacesByHostElement.get(elm);
|
||||||
|
|
||||||
|
@ -273,9 +274,7 @@ export class AnimationTransitionNamespace {
|
||||||
|
|
||||||
removeNode(element: any, context: any, doNotRecurse?: boolean): void {
|
removeNode(element: any, context: any, doNotRecurse?: boolean): void {
|
||||||
const engine = this._engine;
|
const engine = this._engine;
|
||||||
|
engine.markElementAsRemoved(element);
|
||||||
addClass(element, LEAVE_CLASSNAME);
|
|
||||||
engine.afterFlush(() => removeClass(element, LEAVE_CLASSNAME));
|
|
||||||
|
|
||||||
if (!doNotRecurse && element.childElementCount) {
|
if (!doNotRecurse && element.childElementCount) {
|
||||||
this._destroyInnerNodes(element, context, true);
|
this._destroyInnerNodes(element, context, true);
|
||||||
|
@ -382,7 +381,7 @@ export class AnimationTransitionNamespace {
|
||||||
|
|
||||||
insertNode(element: any, parent: any): void { addClass(element, this._hostClassName); }
|
insertNode(element: any, parent: any): void { addClass(element, this._hostClassName); }
|
||||||
|
|
||||||
drainQueuedTransitions(countId: number): QueueInstruction[] {
|
drainQueuedTransitions(microtaskId: number): QueueInstruction[] {
|
||||||
const instructions: QueueInstruction[] = [];
|
const instructions: QueueInstruction[] = [];
|
||||||
this._queue.forEach(entry => {
|
this._queue.forEach(entry => {
|
||||||
const player = entry.player;
|
const player = entry.player;
|
||||||
|
@ -395,7 +394,7 @@ export class AnimationTransitionNamespace {
|
||||||
if (listener.name == entry.triggerName) {
|
if (listener.name == entry.triggerName) {
|
||||||
const baseEvent = makeAnimationEvent(
|
const baseEvent = makeAnimationEvent(
|
||||||
element, entry.triggerName, entry.fromState.value, entry.toState.value);
|
element, entry.triggerName, entry.fromState.value, entry.toState.value);
|
||||||
(baseEvent as any)['_data'] = countId;
|
(baseEvent as any)['_data'] = microtaskId;
|
||||||
listenOnPlayer(entry.player, listener.phase, baseEvent, listener.callback);
|
listenOnPlayer(entry.player, listener.phase, baseEvent, listener.callback);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -449,13 +448,13 @@ export interface QueuedTransition {
|
||||||
export class TransitionAnimationEngine {
|
export class TransitionAnimationEngine {
|
||||||
public players: TransitionAnimationPlayer[] = [];
|
public players: TransitionAnimationPlayer[] = [];
|
||||||
public queuedRemovals = new Map<any, () => any>();
|
public queuedRemovals = new Map<any, () => any>();
|
||||||
public newlyInserted = new Set<any>();
|
|
||||||
public newHostElements = new Map<any, AnimationTransitionNamespace>();
|
public newHostElements = new Map<any, AnimationTransitionNamespace>();
|
||||||
public playersByElement = new Map<any, TransitionAnimationPlayer[]>();
|
public playersByElement = new Map<any, TransitionAnimationPlayer[]>();
|
||||||
public playersByQueriedElement = new Map<any, TransitionAnimationPlayer[]>();
|
public playersByQueriedElement = new Map<any, TransitionAnimationPlayer[]>();
|
||||||
public statesByElement = new Map<any, {[triggerName: string]: StateValue}>();
|
public statesByElement = new Map<any, {[triggerName: string]: StateValue}>();
|
||||||
public totalAnimations = 0;
|
public totalAnimations = 0;
|
||||||
public totalQueuedPlayers = 0;
|
public totalQueuedPlayers = 0;
|
||||||
|
public currentEpochId = 0;
|
||||||
|
|
||||||
private _namespaceLookup: {[id: string]: AnimationTransitionNamespace} = {};
|
private _namespaceLookup: {[id: string]: AnimationTransitionNamespace} = {};
|
||||||
private _namespaceList: AnimationTransitionNamespace[] = [];
|
private _namespaceList: AnimationTransitionNamespace[] = [];
|
||||||
|
@ -498,7 +497,7 @@ export class TransitionAnimationEngine {
|
||||||
// animation renderer type. If this happens then we can still have
|
// animation renderer type. If this happens then we can still have
|
||||||
// access to this item when we query for :enter nodes. If the parent
|
// access to this item when we query for :enter nodes. If the parent
|
||||||
// is a renderer then the set data-structure will normalize the entry
|
// is a renderer then the set data-structure will normalize the entry
|
||||||
this.newlyInserted.add(hostElement);
|
this.updateElementEpoch(hostElement);
|
||||||
}
|
}
|
||||||
return this._namespaceLookup[namespaceId] = ns;
|
return this._namespaceLookup[namespaceId] = ns;
|
||||||
}
|
}
|
||||||
|
@ -526,17 +525,24 @@ export class TransitionAnimationEngine {
|
||||||
return ns;
|
return ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
register(namespaceId: string, hostElement: any, name: string, trigger: AnimationTrigger) {
|
register(namespaceId: string, hostElement: any) {
|
||||||
let ns = this._namespaceLookup[namespaceId];
|
let ns = this._namespaceLookup[namespaceId];
|
||||||
if (!ns) {
|
if (!ns) {
|
||||||
ns = this.createNamespace(namespaceId, hostElement);
|
ns = this.createNamespace(namespaceId, hostElement);
|
||||||
}
|
}
|
||||||
if (ns.register(name, trigger)) {
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerTrigger(namespaceId: string, name: string, trigger: AnimationTrigger) {
|
||||||
|
let ns = this._namespaceLookup[namespaceId];
|
||||||
|
if (ns && ns.register(name, trigger)) {
|
||||||
this.totalAnimations++;
|
this.totalAnimations++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(namespaceId: string, context: any) {
|
destroy(namespaceId: string, context: any) {
|
||||||
|
if (!namespaceId) return;
|
||||||
|
|
||||||
const ns = this._fetchNamespace(namespaceId);
|
const ns = this._fetchNamespace(namespaceId);
|
||||||
|
|
||||||
this.afterFlush(() => {
|
this.afterFlush(() => {
|
||||||
|
@ -564,20 +570,51 @@ export class TransitionAnimationEngine {
|
||||||
insertNode(namespaceId: string, element: any, parent: any, insertBefore: boolean): void {
|
insertNode(namespaceId: string, element: any, parent: any, insertBefore: boolean): void {
|
||||||
if (!isElementNode(element)) return;
|
if (!isElementNode(element)) return;
|
||||||
|
|
||||||
this._fetchNamespace(namespaceId).insertNode(element, parent);
|
// special case for when an element is removed and reinserted (move operation)
|
||||||
|
// when this occurs we do not want to use the element for deletion later
|
||||||
|
if (this.queuedRemovals.has(element)) {
|
||||||
|
this.markElementAsRemoved(element, true);
|
||||||
|
this.queuedRemovals.delete(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in the event that the namespaceId is blank then the caller
|
||||||
|
// code does not contain any animation code in it, but it is
|
||||||
|
// just being called so that the node is marked as being inserted
|
||||||
|
if (namespaceId) {
|
||||||
|
this._fetchNamespace(namespaceId).insertNode(element, parent);
|
||||||
|
}
|
||||||
|
|
||||||
// only *directives and host elements are inserted before
|
// only *directives and host elements are inserted before
|
||||||
if (insertBefore) {
|
if (insertBefore) {
|
||||||
this.newlyInserted.add(element);
|
this.updateElementEpoch(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateElementEpoch(element: any, isRemoval?: boolean) {
|
||||||
|
const epoch = (isRemoval ? -1 : 1) * this.currentEpochId;
|
||||||
|
setAttribute(element, ANIMATE_EPOCH_ATTR, epoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
markElementAsRemoved(element: any, unmark?: boolean) {
|
||||||
|
if (unmark) {
|
||||||
|
removeClass(element, LEAVE_CLASSNAME);
|
||||||
|
} else {
|
||||||
|
addClass(element, LEAVE_CLASSNAME);
|
||||||
|
this.afterFlush(() => removeClass(element, LEAVE_CLASSNAME));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeNode(namespaceId: string, element: any, context: any, doNotRecurse?: boolean): void {
|
removeNode(namespaceId: string, element: any, context: any, doNotRecurse?: boolean): void {
|
||||||
const ns = this._fetchNamespace(namespaceId);
|
if (namespaceId) {
|
||||||
if (!isElementNode(element) || !ns) {
|
const ns = this._fetchNamespace(namespaceId);
|
||||||
this._onRemovalComplete(element, context);
|
if (!isElementNode(element) || !ns) {
|
||||||
|
this._onRemovalComplete(element, context);
|
||||||
|
} else {
|
||||||
|
ns.removeNode(element, context, doNotRecurse);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ns.removeNode(element, context, doNotRecurse);
|
this.markElementAsRemoved(element);
|
||||||
|
this.queuedRemovals.set(element, () => this._onRemovalComplete(element, context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +634,7 @@ export class TransitionAnimationEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyInnerAnimations(containerElement: any) {
|
destroyInnerAnimations(containerElement: any) {
|
||||||
listToArray(this.driver.query(containerElement, NG_TRIGGER_SELECTOR, true)).forEach(element => {
|
this.driver.query(containerElement, NG_TRIGGER_SELECTOR, true).forEach(element => {
|
||||||
const players = this.playersByElement.get(element);
|
const players = this.playersByElement.get(element);
|
||||||
if (players) {
|
if (players) {
|
||||||
players.forEach(player => {
|
players.forEach(player => {
|
||||||
|
@ -628,20 +665,21 @@ export class TransitionAnimationEngine {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
flush(countId: number = -1) {
|
flush(microtaskId: number = -1) {
|
||||||
let players: AnimationPlayer[] = [];
|
let players: AnimationPlayer[] = [];
|
||||||
if (this.newHostElements.size) {
|
if (this.newHostElements.size) {
|
||||||
this.newHostElements.forEach((ns, element) => { this._balanceNamespaceList(ns, element); });
|
this.newHostElements.forEach((ns, element) => this._balanceNamespaceList(ns, element));
|
||||||
this.newHostElements.clear();
|
this.newHostElements.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._namespaceList.length && (this.totalQueuedPlayers || this.queuedRemovals.size)) {
|
if (this._namespaceList.length && (this.totalQueuedPlayers || this.queuedRemovals.size)) {
|
||||||
players = this._flushAnimations(countId);
|
players = this._flushAnimations(microtaskId);
|
||||||
|
} else {
|
||||||
|
this.queuedRemovals.forEach(fn => fn());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.totalQueuedPlayers = 0;
|
this.totalQueuedPlayers = 0;
|
||||||
this.queuedRemovals.clear();
|
this.queuedRemovals.clear();
|
||||||
this.newlyInserted.clear();
|
|
||||||
this._flushFns.forEach(fn => fn());
|
this._flushFns.forEach(fn => fn());
|
||||||
this._flushFns = [];
|
this._flushFns = [];
|
||||||
|
|
||||||
|
@ -658,9 +696,11 @@ export class TransitionAnimationEngine {
|
||||||
quietFns.forEach(fn => fn());
|
quietFns.forEach(fn => fn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.currentEpochId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _flushAnimations(countId: number): TransitionAnimationPlayer[] {
|
private _flushAnimations(microtaskId: number): TransitionAnimationPlayer[] {
|
||||||
const subTimelines = new ElementInstructionMap();
|
const subTimelines = new ElementInstructionMap();
|
||||||
const skippedPlayers: TransitionAnimationPlayer[] = [];
|
const skippedPlayers: TransitionAnimationPlayer[] = [];
|
||||||
const skippedPlayersMap = new Map<any, AnimationPlayer[]>();
|
const skippedPlayersMap = new Map<any, AnimationPlayer[]>();
|
||||||
|
@ -672,13 +712,15 @@ export class TransitionAnimationEngine {
|
||||||
// this must occur before the instructions are built below such that
|
// this must occur before the instructions are built below such that
|
||||||
// the :enter queries match the elements (since the timeline queries
|
// the :enter queries match the elements (since the timeline queries
|
||||||
// are fired during instruction building).
|
// are fired during instruction building).
|
||||||
const allEnterNodes = iteratorToArray(this.newlyInserted.values());
|
|
||||||
const enterNodes: any[] = collectEnterElements(this.driver, allEnterNodes);
|
|
||||||
const bodyNode = getBodyNode();
|
const bodyNode = getBodyNode();
|
||||||
|
const allEnterNodes: any[] =
|
||||||
|
bodyNode ? this.driver.query(bodyNode, makeEpochSelector(this.currentEpochId), true) : [];
|
||||||
|
const enterNodes: any[] =
|
||||||
|
allEnterNodes.length ? collectEnterElements(this.driver, allEnterNodes) : [];
|
||||||
|
|
||||||
for (let i = this._namespaceList.length - 1; i >= 0; i--) {
|
for (let i = this._namespaceList.length - 1; i >= 0; i--) {
|
||||||
const ns = this._namespaceList[i];
|
const ns = this._namespaceList[i];
|
||||||
ns.drainQueuedTransitions(countId).forEach(entry => {
|
ns.drainQueuedTransitions(microtaskId).forEach(entry => {
|
||||||
const player = entry.player;
|
const player = entry.player;
|
||||||
|
|
||||||
const element = entry.element;
|
const element = entry.element;
|
||||||
|
@ -751,7 +793,7 @@ export class TransitionAnimationEngine {
|
||||||
allPreviousPlayersMap.forEach(players => players.forEach(player => player.destroy()));
|
allPreviousPlayersMap.forEach(players => players.forEach(player => player.destroy()));
|
||||||
|
|
||||||
const leaveNodes: any[] = bodyNode && allPostStyleElements.size ?
|
const leaveNodes: any[] = bodyNode && allPostStyleElements.size ?
|
||||||
listToArray(this.driver.query(bodyNode, LEAVE_SELECTOR, true)) :
|
this.driver.query(bodyNode, LEAVE_SELECTOR, true) :
|
||||||
[];
|
[];
|
||||||
|
|
||||||
// PRE STAGE: fill the ! styles
|
// PRE STAGE: fill the ! styles
|
||||||
|
@ -866,7 +908,6 @@ export class TransitionAnimationEngine {
|
||||||
elementContainsData(namespaceId: string, element: any) {
|
elementContainsData(namespaceId: string, element: any) {
|
||||||
let containsData = false;
|
let containsData = false;
|
||||||
if (this.queuedRemovals.has(element)) containsData = true;
|
if (this.queuedRemovals.has(element)) containsData = true;
|
||||||
if (this.newlyInserted.has(element)) containsData = true;
|
|
||||||
if (this.playersByElement.has(element)) containsData = true;
|
if (this.playersByElement.has(element)) containsData = true;
|
||||||
if (this.playersByQueriedElement.has(element)) containsData = true;
|
if (this.playersByQueriedElement.has(element)) containsData = true;
|
||||||
if (this.statesByElement.has(element)) containsData = true;
|
if (this.statesByElement.has(element)) containsData = true;
|
||||||
|
@ -1217,12 +1258,6 @@ function cloakAndComputeStyles(
|
||||||
return valuesMap;
|
return valuesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
function listToArray(list: any): any[] {
|
|
||||||
const arr: any[] = [];
|
|
||||||
arr.push(...(list as any[]));
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectEnterElements(driver: AnimationDriver, allEnterNodes: any[]) {
|
function collectEnterElements(driver: AnimationDriver, allEnterNodes: any[]) {
|
||||||
allEnterNodes.forEach(element => addClass(element, POTENTIAL_ENTER_CLASSNAME));
|
allEnterNodes.forEach(element => addClass(element, POTENTIAL_ENTER_CLASSNAME));
|
||||||
const enterNodes = filterNodeClasses(driver, getBodyNode(), POTENTIAL_ENTER_SELECTOR);
|
const enterNodes = filterNodeClasses(driver, getBodyNode(), POTENTIAL_ENTER_SELECTOR);
|
||||||
|
@ -1264,9 +1299,22 @@ function removeClass(element: any, className: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setAttribute(element: any, attr: string, value: any) {
|
||||||
|
if (element.setAttribute) {
|
||||||
|
element.setAttribute(attr, value);
|
||||||
|
} else {
|
||||||
|
element[attr] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getBodyNode(): any|null {
|
function getBodyNode(): any|null {
|
||||||
if (typeof document != 'undefined') {
|
if (typeof document != 'undefined') {
|
||||||
return document.body;
|
return document.body;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeEpochSelector(epochId: number, isRemoval?: boolean) {
|
||||||
|
const value = (isRemoval ? -1 : 1) * epochId;
|
||||||
|
return `[${ANIMATE_EPOCH_ATTR}="${value}"]`;
|
||||||
|
}
|
||||||
|
|
|
@ -660,7 +660,8 @@ function registerTrigger(
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
}
|
}
|
||||||
const trigger = buildTrigger(name, ast);
|
const trigger = buildTrigger(name, ast);
|
||||||
engine.register(id, element, name, trigger)
|
engine.register(id, element);
|
||||||
|
engine.registerTrigger(id, name, trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setProperty(
|
function setProperty(
|
||||||
|
|
|
@ -1101,9 +1101,10 @@ export function main() {
|
||||||
const cmp = fixture.componentInstance;
|
const cmp = fixture.componentInstance;
|
||||||
|
|
||||||
const someTrigger = trigger('someTrigger', []);
|
const someTrigger = trigger('someTrigger', []);
|
||||||
|
const hostElement = fixture.nativeElement;
|
||||||
|
engine.register(DEFAULT_NAMESPACE_ID, hostElement);
|
||||||
engine.registerTrigger(
|
engine.registerTrigger(
|
||||||
DEFAULT_COMPONENT_ID, DEFAULT_NAMESPACE_ID, fixture.nativeElement, someTrigger.name,
|
DEFAULT_COMPONENT_ID, DEFAULT_NAMESPACE_ID, hostElement, someTrigger.name, someTrigger);
|
||||||
someTrigger);
|
|
||||||
|
|
||||||
cmp.exp = 'a';
|
cmp.exp = 'a';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
|
@ -1084,6 +1084,107 @@ export function main() {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should query elements in sub components that do not contain animations using the :enter selector',
|
||||||
|
() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'parent-cmp',
|
||||||
|
template: `
|
||||||
|
<div [@myAnimation]="exp">
|
||||||
|
<child-cmp #child></child-cmp>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
animations: [trigger(
|
||||||
|
'myAnimation',
|
||||||
|
[transition(
|
||||||
|
'* => on',
|
||||||
|
[query(
|
||||||
|
':enter', [style({opacity: 0}), animate(1000, style({opacity: 1}))])])])]
|
||||||
|
})
|
||||||
|
class ParentCmp {
|
||||||
|
public exp: any;
|
||||||
|
|
||||||
|
@ViewChild('child') public child: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child-cmp',
|
||||||
|
template: `
|
||||||
|
<div *ngFor="let item of items">
|
||||||
|
{{ item }}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class ChildCmp {
|
||||||
|
public items: any[] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
|
||||||
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
cmp.exp = 'on';
|
||||||
|
cmp.child.items = [1, 2, 3];
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const players = getLog() as any[];
|
||||||
|
expect(players.length).toEqual(3);
|
||||||
|
|
||||||
|
expect(players[0].element.innerText.trim()).toEqual('1');
|
||||||
|
expect(players[1].element.innerText.trim()).toEqual('2');
|
||||||
|
expect(players[2].element.innerText.trim()).toEqual('3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should query elements in sub components that do not contain animations using the :leave selector',
|
||||||
|
() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'parent-cmp',
|
||||||
|
template: `
|
||||||
|
<div [@myAnimation]="exp">
|
||||||
|
<child-cmp #child></child-cmp>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
animations: [trigger(
|
||||||
|
'myAnimation',
|
||||||
|
[transition(
|
||||||
|
'* => on', [query(':leave', [animate(1000, style({opacity: 0}))])])])]
|
||||||
|
})
|
||||||
|
class ParentCmp {
|
||||||
|
public exp: any;
|
||||||
|
|
||||||
|
@ViewChild('child') public child: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child-cmp',
|
||||||
|
template: `
|
||||||
|
<div *ngFor="let item of items">
|
||||||
|
{{ item }}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class ChildCmp {
|
||||||
|
public items: any[] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
|
||||||
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
cmp.child.items = [4, 5, 6];
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
cmp.exp = 'on';
|
||||||
|
cmp.child.items = [];
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const players = getLog() as any[];
|
||||||
|
expect(players.length).toEqual(3);
|
||||||
|
|
||||||
|
expect(players[0].element.innerText.trim()).toEqual('4');
|
||||||
|
expect(players[1].element.innerText.trim()).toEqual('5');
|
||||||
|
expect(players[2].element.innerText.trim()).toEqual('6');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('sub triggers', () => {
|
describe('sub triggers', () => {
|
||||||
|
|
|
@ -130,11 +130,13 @@ export function main() {
|
||||||
.map(de => de.injector.get(ManualViewportDirective));
|
.map(de => de.injector.get(ManualViewportDirective));
|
||||||
|
|
||||||
expect(main.nativeElement).toHaveText('(, B)');
|
expect(main.nativeElement).toHaveText('(, B)');
|
||||||
|
|
||||||
viewportDirectives.forEach(d => d.show());
|
viewportDirectives.forEach(d => d.show());
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(A1, B)');
|
expect(main.nativeElement).toHaveText('(A1, B)');
|
||||||
|
|
||||||
viewportDirectives.forEach(d => d.hide());
|
viewportDirectives.forEach(d => d.hide());
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(, B)');
|
expect(main.nativeElement).toHaveText('(, B)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -200,10 +202,11 @@ export function main() {
|
||||||
expect(main.nativeElement).toHaveText('(, BC)');
|
expect(main.nativeElement).toHaveText('(, BC)');
|
||||||
|
|
||||||
viewportDirective.show();
|
viewportDirective.show();
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(A, BC)');
|
expect(main.nativeElement).toHaveText('(A, BC)');
|
||||||
|
|
||||||
viewportDirective.hide();
|
viewportDirective.hide();
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(, BC)');
|
expect(main.nativeElement).toHaveText('(, BC)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -492,7 +495,7 @@ export function main() {
|
||||||
expect(main.nativeElement).toHaveText('(, D)');
|
expect(main.nativeElement).toHaveText('(, D)');
|
||||||
|
|
||||||
viewViewportDir.show();
|
viewViewportDir.show();
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(AC, D)');
|
expect(main.nativeElement).toHaveText('(AC, D)');
|
||||||
|
|
||||||
const contentViewportDir =
|
const contentViewportDir =
|
||||||
|
@ -500,12 +503,13 @@ export function main() {
|
||||||
ManualViewportDirective);
|
ManualViewportDirective);
|
||||||
|
|
||||||
contentViewportDir.show();
|
contentViewportDir.show();
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(ABC, D)');
|
expect(main.nativeElement).toHaveText('(ABC, D)');
|
||||||
|
|
||||||
// hide view viewport, and test that it also hides
|
// hide view viewport, and test that it also hides
|
||||||
// the content viewport's views
|
// the content viewport's views
|
||||||
viewViewportDir.hide();
|
viewViewportDir.hide();
|
||||||
|
main.detectChanges();
|
||||||
expect(main.nativeElement).toHaveText('(, D)');
|
expect(main.nativeElement).toHaveText('(, D)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -62,6 +62,7 @@ export function main() {
|
||||||
[elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child1']])]))
|
[elementDef(NodeFlags.None, null !, null !, 0, 'span', [['name', 'child1']])]))
|
||||||
]));
|
]));
|
||||||
const viewContainerData = asElementData(parentView, 1);
|
const viewContainerData = asElementData(parentView, 1);
|
||||||
|
const rf = parentView.root.rendererFactory;
|
||||||
|
|
||||||
const childView0 = createEmbeddedView(parentView, parentView.def.nodes[1]);
|
const childView0 = createEmbeddedView(parentView, parentView.def.nodes[1]);
|
||||||
const childView1 = createEmbeddedView(parentView, parentView.def.nodes[2]);
|
const childView1 = createEmbeddedView(parentView, parentView.def.nodes[2]);
|
||||||
|
@ -75,8 +76,10 @@ export function main() {
|
||||||
expect(getDOM().getAttribute(rootChildren[1], 'name')).toBe('child0');
|
expect(getDOM().getAttribute(rootChildren[1], 'name')).toBe('child0');
|
||||||
expect(getDOM().getAttribute(rootChildren[2], 'name')).toBe('child1');
|
expect(getDOM().getAttribute(rootChildren[2], 'name')).toBe('child1');
|
||||||
|
|
||||||
|
rf.begin !();
|
||||||
detachEmbeddedView(viewContainerData, 1);
|
detachEmbeddedView(viewContainerData, 1);
|
||||||
detachEmbeddedView(viewContainerData, 0);
|
detachEmbeddedView(viewContainerData, 0);
|
||||||
|
rf.end !();
|
||||||
|
|
||||||
expect(getDOM().childNodes(rootNodes[0]).length).toBe(2);
|
expect(getDOM().childNodes(rootNodes[0]).length).toBe(2);
|
||||||
});
|
});
|
||||||
|
@ -187,4 +190,4 @@ export function main() {
|
||||||
expect(log).toEqual(['ngOnDestroy']);
|
expect(log).toEqual(['ngOnDestroy']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ export function main() {
|
||||||
])));
|
])));
|
||||||
|
|
||||||
const componentView = asElementData(view, 0).componentView;
|
const componentView = asElementData(view, 0).componentView;
|
||||||
|
const rf = componentView.root.rendererFactory;
|
||||||
const view0 = createEmbeddedView(componentView, componentView.def.nodes[1]);
|
const view0 = createEmbeddedView(componentView, componentView.def.nodes[1]);
|
||||||
|
|
||||||
attachEmbeddedView(view, asElementData(componentView, 1), 0, view0);
|
attachEmbeddedView(view, asElementData(componentView, 1), 0, view0);
|
||||||
|
@ -128,7 +129,9 @@ export function main() {
|
||||||
expect(getDOM().childNodes(getDOM().firstChild(rootNodes[0]))[1])
|
expect(getDOM().childNodes(getDOM().firstChild(rootNodes[0]))[1])
|
||||||
.toBe(asTextData(view, 2).renderText);
|
.toBe(asTextData(view, 2).renderText);
|
||||||
|
|
||||||
|
rf.begin !();
|
||||||
detachEmbeddedView(asElementData(componentView, 1), 0);
|
detachEmbeddedView(asElementData(componentView, 1), 0);
|
||||||
|
rf.end !();
|
||||||
expect(getDOM().childNodes(getDOM().firstChild(rootNodes[0])).length).toBe(1);
|
expect(getDOM().childNodes(getDOM().firstChild(rootNodes[0])).length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,13 @@ import {Injectable, NgZone, Renderer2, RendererFactory2, RendererStyleFlags2, Re
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AnimationRendererFactory implements RendererFactory2 {
|
export class AnimationRendererFactory implements RendererFactory2 {
|
||||||
private _currentId: number = 0;
|
private _currentId: number = 0;
|
||||||
private _currentFlushId: number = 1;
|
private _microtaskId: number = 1;
|
||||||
private _animationCallbacksBuffer: [(e: any) => any, any][] = [];
|
private _animationCallbacksBuffer: [(e: any) => any, any][] = [];
|
||||||
|
private _rendererCache = new Map<Renderer2, BaseAnimationRenderer>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private delegate: RendererFactory2, private _engine: AnimationEngine, private _zone: NgZone) {
|
private delegate: RendererFactory2, private engine: AnimationEngine, private _zone: NgZone) {
|
||||||
_engine.onRemovalComplete = (element: any, delegate: any) => {
|
engine.onRemovalComplete = (element: any, delegate: Renderer2) => {
|
||||||
// Note: if an component element has a leave animation, and the component
|
// Note: if an component element has a leave animation, and the component
|
||||||
// a host leave animation, the view engine will call `removeChild` for the parent
|
// a host leave animation, the view engine will call `removeChild` for the parent
|
||||||
// component renderer as well as for the child component renderer.
|
// component renderer as well as for the child component renderer.
|
||||||
|
@ -29,18 +30,31 @@ export class AnimationRendererFactory implements RendererFactory2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
createRenderer(hostElement: any, type: RendererType2): Renderer2 {
|
createRenderer(hostElement: any, type: RendererType2): Renderer2 {
|
||||||
let delegate = this.delegate.createRenderer(hostElement, type);
|
const EMPTY_NAMESPACE_ID = '';
|
||||||
if (!hostElement || !type || !type.data || !type.data['animation']) return delegate;
|
|
||||||
|
// cache the delegates to find out which cached delegate can
|
||||||
|
// be used by which cached renderer
|
||||||
|
const delegate = this.delegate.createRenderer(hostElement, type);
|
||||||
|
if (!hostElement || !type || !type.data || !type.data['animation']) {
|
||||||
|
let renderer: BaseAnimationRenderer|undefined = this._rendererCache.get(delegate);
|
||||||
|
if (!renderer) {
|
||||||
|
renderer = new BaseAnimationRenderer(EMPTY_NAMESPACE_ID, delegate, this.engine);
|
||||||
|
// only cache this result when the base renderer is used
|
||||||
|
this._rendererCache.set(delegate, renderer);
|
||||||
|
}
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
const componentId = type.id;
|
const componentId = type.id;
|
||||||
const namespaceId = type.id + '-' + this._currentId;
|
const namespaceId = type.id + '-' + this._currentId;
|
||||||
this._currentId++;
|
this._currentId++;
|
||||||
|
|
||||||
|
this.engine.register(namespaceId, hostElement);
|
||||||
const animationTriggers = type.data['animation'] as AnimationTriggerMetadata[];
|
const animationTriggers = type.data['animation'] as AnimationTriggerMetadata[];
|
||||||
animationTriggers.forEach(
|
animationTriggers.forEach(
|
||||||
trigger => this._engine.registerTrigger(
|
trigger => this.engine.registerTrigger(
|
||||||
componentId, namespaceId, hostElement, trigger.name, trigger));
|
componentId, namespaceId, hostElement, trigger.name, trigger));
|
||||||
return new AnimationRenderer(this, delegate, this._engine, this._zone, namespaceId);
|
return new AnimationRenderer(this, namespaceId, delegate, this.engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
begin() {
|
begin() {
|
||||||
|
@ -50,13 +64,12 @@ export class AnimationRendererFactory implements RendererFactory2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _scheduleCountTask() {
|
private _scheduleCountTask() {
|
||||||
Zone.current.scheduleMicroTask(
|
Zone.current.scheduleMicroTask('incremenet the animation microtask', () => this._microtaskId++);
|
||||||
'incremenet the animation microtask', () => { this._currentFlushId++; });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
scheduleListenerCallback(count: number, fn: (e: any) => any, data: any) {
|
scheduleListenerCallback(count: number, fn: (e: any) => any, data: any) {
|
||||||
if (count >= 0 && count < this._currentFlushId) {
|
if (count >= 0 && count < this._microtaskId) {
|
||||||
this._zone.run(() => fn(data));
|
this._zone.run(() => fn(data));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -79,54 +92,64 @@ export class AnimationRendererFactory implements RendererFactory2 {
|
||||||
end() {
|
end() {
|
||||||
this._zone.runOutsideAngular(() => {
|
this._zone.runOutsideAngular(() => {
|
||||||
this._scheduleCountTask();
|
this._scheduleCountTask();
|
||||||
this._engine.flush(this._currentFlushId);
|
this.engine.flush(this._microtaskId);
|
||||||
});
|
});
|
||||||
if (this.delegate.end) {
|
if (this.delegate.end) {
|
||||||
this.delegate.end();
|
this.delegate.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
whenRenderingDone(): Promise<any> { return this._engine.whenRenderingDone(); }
|
whenRenderingDone(): Promise<any> { return this.engine.whenRenderingDone(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AnimationRenderer implements Renderer2 {
|
export class BaseAnimationRenderer implements Renderer2 {
|
||||||
public destroyNode: ((node: any) => any)|null = null;
|
|
||||||
public microtaskCount: number = 0;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _factory: AnimationRendererFactory, public delegate: Renderer2,
|
protected namespaceId: string, public delegate: Renderer2, public engine: AnimationEngine) {
|
||||||
private _engine: AnimationEngine, private _zone: NgZone, private _namespaceId: string) {
|
|
||||||
this.destroyNode = this.delegate.destroyNode ? (n) => delegate.destroyNode !(n) : null;
|
this.destroyNode = this.delegate.destroyNode ? (n) => delegate.destroyNode !(n) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get data() { return this.delegate.data; }
|
get data() { return this.delegate.data; }
|
||||||
|
|
||||||
|
destroyNode: ((n: any) => void)|null;
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
this._engine.destroy(this._namespaceId, this.delegate);
|
this.engine.destroy(this.namespaceId, this.delegate);
|
||||||
this.delegate.destroy();
|
this.delegate.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
createElement(name: string, namespace?: string): any {
|
createElement(name: string, namespace?: string|null|undefined) {
|
||||||
return this.delegate.createElement(name, namespace);
|
return this.delegate.createElement(name, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComment(value: string): any { return this.delegate.createComment(value); }
|
createComment(value: string) { return this.delegate.createComment(value); }
|
||||||
|
|
||||||
createText(value: string): any { return this.delegate.createText(value); }
|
createText(value: string) { return this.delegate.createText(value); }
|
||||||
|
|
||||||
selectRootElement(selectorOrNode: string|any): any {
|
appendChild(parent: any, newChild: any): void {
|
||||||
return this.delegate.selectRootElement(selectorOrNode);
|
this.delegate.appendChild(parent, newChild);
|
||||||
|
this.engine.onInsert(this.namespaceId, newChild, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
parentNode(node: any): any { return this.delegate.parentNode(node); }
|
insertBefore(parent: any, newChild: any, refChild: any): void {
|
||||||
|
this.delegate.insertBefore(parent, newChild, refChild);
|
||||||
|
this.engine.onInsert(this.namespaceId, newChild, parent, true);
|
||||||
|
}
|
||||||
|
|
||||||
nextSibling(node: any): any { return this.delegate.nextSibling(node); }
|
removeChild(parent: any, oldChild: any): void {
|
||||||
|
this.engine.onRemove(this.namespaceId, oldChild, this.delegate);
|
||||||
|
}
|
||||||
|
|
||||||
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
selectRootElement(selectorOrNode: any) { return this.delegate.selectRootElement(selectorOrNode); }
|
||||||
|
|
||||||
|
parentNode(node: any) { return this.delegate.parentNode(node); }
|
||||||
|
|
||||||
|
nextSibling(node: any) { return this.delegate.nextSibling(node); }
|
||||||
|
|
||||||
|
setAttribute(el: any, name: string, value: string, namespace?: string|null|undefined): void {
|
||||||
this.delegate.setAttribute(el, name, value, namespace);
|
this.delegate.setAttribute(el, name, value, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAttribute(el: any, name: string, namespace?: string): void {
|
removeAttribute(el: any, name: string, namespace?: string|null|undefined): void {
|
||||||
this.delegate.removeAttribute(el, name, namespace);
|
this.delegate.removeAttribute(el, name, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,34 +157,37 @@ export class AnimationRenderer implements Renderer2 {
|
||||||
|
|
||||||
removeClass(el: any, name: string): void { this.delegate.removeClass(el, name); }
|
removeClass(el: any, name: string): void { this.delegate.removeClass(el, name); }
|
||||||
|
|
||||||
setStyle(el: any, style: string, value: any, flags: RendererStyleFlags2): void {
|
setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2|undefined): void {
|
||||||
this.delegate.setStyle(el, style, value, flags);
|
this.delegate.setStyle(el, style, value, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeStyle(el: any, style: string, flags: RendererStyleFlags2): void {
|
removeStyle(el: any, style: string, flags?: RendererStyleFlags2|undefined): void {
|
||||||
this.delegate.removeStyle(el, style, flags);
|
this.delegate.removeStyle(el, style, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setProperty(el: any, name: string, value: any): void {
|
||||||
|
this.delegate.setProperty(el, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
setValue(node: any, value: string): void { this.delegate.setValue(node, value); }
|
setValue(node: any, value: string): void { this.delegate.setValue(node, value); }
|
||||||
|
|
||||||
appendChild(parent: any, newChild: any): void {
|
listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void {
|
||||||
this.delegate.appendChild(parent, newChild);
|
return this.delegate.listen(target, eventName, callback);
|
||||||
this._engine.onInsert(this._namespaceId, newChild, parent, false);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
insertBefore(parent: any, newChild: any, refChild: any): void {
|
export class AnimationRenderer extends BaseAnimationRenderer implements Renderer2 {
|
||||||
this.delegate.insertBefore(parent, newChild, refChild);
|
constructor(
|
||||||
this._engine.onInsert(this._namespaceId, newChild, parent, true);
|
public factory: AnimationRendererFactory, namespaceId: string, delegate: Renderer2,
|
||||||
}
|
engine: AnimationEngine) {
|
||||||
|
super(namespaceId, delegate, engine);
|
||||||
removeChild(parent: any, oldChild: any): void {
|
this.namespaceId = namespaceId;
|
||||||
this._engine.onRemove(this._namespaceId, oldChild, this.delegate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperty(el: any, name: string, value: any): void {
|
setProperty(el: any, name: string, value: any): void {
|
||||||
if (name.charAt(0) == '@') {
|
if (name.charAt(0) == '@') {
|
||||||
name = name.substr(1);
|
name = name.substr(1);
|
||||||
this._engine.setProperty(this._namespaceId, el, name, value);
|
this.engine.setProperty(this.namespaceId, el, name, value);
|
||||||
} else {
|
} else {
|
||||||
this.delegate.setProperty(el, name, value);
|
this.delegate.setProperty(el, name, value);
|
||||||
}
|
}
|
||||||
|
@ -176,9 +202,9 @@ export class AnimationRenderer implements Renderer2 {
|
||||||
if (name.charAt(0) != '@') { // transition-specific
|
if (name.charAt(0) != '@') { // transition-specific
|
||||||
[name, phase] = parseTriggerCallbackName(name);
|
[name, phase] = parseTriggerCallbackName(name);
|
||||||
}
|
}
|
||||||
return this._engine.listen(this._namespaceId, element, name, phase, event => {
|
return this.engine.listen(this.namespaceId, element, name, phase, event => {
|
||||||
const countId = (event as any)['_data'] || -1;
|
const countId = (event as any)['_data'] || -1;
|
||||||
this._factory.scheduleListenerCallback(countId, callback, event);
|
this.factory.scheduleListenerCallback(countId, callback, event);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this.delegate.listen(target, eventName, callback);
|
return this.delegate.listen(target, eventName, callback);
|
||||||
|
|
Loading…
Reference in New Issue