refactor: move angular source to /packages rather than modules/@angular
This commit is contained in:
194
packages/core/src/view/query.ts
Normal file
194
packages/core/src/view/query.ts
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ElementRef} from '../linker/element_ref';
|
||||
import {QueryList} from '../linker/query_list';
|
||||
import {TemplateRef} from '../linker/template_ref';
|
||||
import {ViewContainerRef} from '../linker/view_container_ref';
|
||||
|
||||
import {createTemplateRef, createViewContainerRef} from './refs';
|
||||
import {NodeDef, NodeFlags, QueryBindingDef, QueryBindingType, QueryDef, QueryValueType, Services, ViewData, asElementData, asProviderData, asQueryList} from './types';
|
||||
import {declaredViewContainer, filterQueryId, isEmbeddedView, viewParentEl} from './util';
|
||||
|
||||
export function queryDef(
|
||||
flags: NodeFlags, id: number, bindings: {[propName: string]: QueryBindingType}): NodeDef {
|
||||
let bindingDefs: QueryBindingDef[] = [];
|
||||
for (let propName in bindings) {
|
||||
const bindingType = bindings[propName];
|
||||
bindingDefs.push({propName, bindingType});
|
||||
}
|
||||
|
||||
return {
|
||||
// will bet set by the view definition
|
||||
index: undefined,
|
||||
parent: undefined,
|
||||
renderParent: undefined,
|
||||
bindingIndex: undefined,
|
||||
outputIndex: undefined,
|
||||
// regular values
|
||||
flags,
|
||||
childFlags: 0,
|
||||
directChildFlags: 0,
|
||||
childMatchedQueries: 0,
|
||||
ngContentIndex: undefined,
|
||||
matchedQueries: {},
|
||||
matchedQueryIds: 0,
|
||||
references: {},
|
||||
childCount: 0,
|
||||
bindings: [],
|
||||
outputs: [],
|
||||
element: undefined,
|
||||
provider: undefined,
|
||||
text: undefined,
|
||||
query: {id, filterId: filterQueryId(id), bindings: bindingDefs},
|
||||
ngContent: undefined
|
||||
};
|
||||
}
|
||||
|
||||
export function createQuery(): QueryList<any> {
|
||||
return new QueryList();
|
||||
}
|
||||
|
||||
export function dirtyParentQueries(view: ViewData) {
|
||||
const queryIds = view.def.nodeMatchedQueries;
|
||||
while (view.parent && isEmbeddedView(view)) {
|
||||
let tplDef = view.parentNodeDef;
|
||||
view = view.parent;
|
||||
// content queries
|
||||
const end = tplDef.index + tplDef.childCount;
|
||||
for (let i = 0; i <= end; i++) {
|
||||
const nodeDef = view.def.nodes[i];
|
||||
if ((nodeDef.flags & NodeFlags.TypeContentQuery) &&
|
||||
(nodeDef.flags & NodeFlags.DynamicQuery) &&
|
||||
(nodeDef.query.filterId & queryIds) === nodeDef.query.filterId) {
|
||||
asQueryList(view, i).setDirty();
|
||||
}
|
||||
if ((nodeDef.flags & NodeFlags.TypeElement && i + nodeDef.childCount < tplDef.index) ||
|
||||
!(nodeDef.childFlags & NodeFlags.TypeContentQuery) ||
|
||||
!(nodeDef.childFlags & NodeFlags.DynamicQuery)) {
|
||||
// skip elements that don't contain the template element or no query.
|
||||
i += nodeDef.childCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// view queries
|
||||
if (view.def.nodeFlags & NodeFlags.TypeViewQuery) {
|
||||
for (let i = 0; i < view.def.nodes.length; i++) {
|
||||
const nodeDef = view.def.nodes[i];
|
||||
if ((nodeDef.flags & NodeFlags.TypeViewQuery) && (nodeDef.flags & NodeFlags.DynamicQuery)) {
|
||||
asQueryList(view, i).setDirty();
|
||||
}
|
||||
// only visit the root nodes
|
||||
i += nodeDef.childCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function checkAndUpdateQuery(view: ViewData, nodeDef: NodeDef) {
|
||||
const queryList = asQueryList(view, nodeDef.index);
|
||||
if (!queryList.dirty) {
|
||||
return;
|
||||
}
|
||||
let directiveInstance: any;
|
||||
let newValues: any[];
|
||||
if (nodeDef.flags & NodeFlags.TypeContentQuery) {
|
||||
const elementDef = nodeDef.parent.parent;
|
||||
newValues = calcQueryValues(
|
||||
view, elementDef.index, elementDef.index + elementDef.childCount, nodeDef.query, []);
|
||||
directiveInstance = asProviderData(view, nodeDef.parent.index).instance;
|
||||
} else if (nodeDef.flags & NodeFlags.TypeViewQuery) {
|
||||
newValues = calcQueryValues(view, 0, view.def.nodes.length - 1, nodeDef.query, []);
|
||||
directiveInstance = view.component;
|
||||
}
|
||||
queryList.reset(newValues);
|
||||
const bindings = nodeDef.query.bindings;
|
||||
let notify = false;
|
||||
for (let i = 0; i < bindings.length; i++) {
|
||||
const binding = bindings[i];
|
||||
let boundValue: any;
|
||||
switch (binding.bindingType) {
|
||||
case QueryBindingType.First:
|
||||
boundValue = queryList.first;
|
||||
break;
|
||||
case QueryBindingType.All:
|
||||
boundValue = queryList;
|
||||
notify = true;
|
||||
break;
|
||||
}
|
||||
directiveInstance[binding.propName] = boundValue;
|
||||
}
|
||||
if (notify) {
|
||||
queryList.notifyOnChanges();
|
||||
}
|
||||
}
|
||||
|
||||
function calcQueryValues(
|
||||
view: ViewData, startIndex: number, endIndex: number, queryDef: QueryDef,
|
||||
values: any[]): any[] {
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
const nodeDef = view.def.nodes[i];
|
||||
const valueType = nodeDef.matchedQueries[queryDef.id];
|
||||
if (valueType != null) {
|
||||
values.push(getQueryValue(view, nodeDef, valueType));
|
||||
}
|
||||
if (nodeDef.flags & NodeFlags.TypeElement && nodeDef.element.template &&
|
||||
(nodeDef.element.template.nodeMatchedQueries & queryDef.filterId) === queryDef.filterId) {
|
||||
// check embedded views that were attached at the place of their template.
|
||||
const elementData = asElementData(view, i);
|
||||
const embeddedViews = elementData.embeddedViews;
|
||||
if (embeddedViews) {
|
||||
for (let k = 0; k < embeddedViews.length; k++) {
|
||||
const embeddedView = embeddedViews[k];
|
||||
const dvc = declaredViewContainer(embeddedView);
|
||||
if (dvc && dvc === elementData) {
|
||||
calcQueryValues(embeddedView, 0, embeddedView.def.nodes.length - 1, queryDef, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
const projectedViews = elementData.projectedViews;
|
||||
if (projectedViews) {
|
||||
for (let k = 0; k < projectedViews.length; k++) {
|
||||
const projectedView = projectedViews[k];
|
||||
calcQueryValues(projectedView, 0, projectedView.def.nodes.length - 1, queryDef, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((nodeDef.childMatchedQueries & queryDef.filterId) !== queryDef.filterId) {
|
||||
// if no child matches the query, skip the children.
|
||||
i += nodeDef.childCount;
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
export function getQueryValue(
|
||||
view: ViewData, nodeDef: NodeDef, queryValueType: QueryValueType): any {
|
||||
if (queryValueType != null) {
|
||||
// a match
|
||||
let value: any;
|
||||
switch (queryValueType) {
|
||||
case QueryValueType.RenderElement:
|
||||
value = asElementData(view, nodeDef.index).renderElement;
|
||||
break;
|
||||
case QueryValueType.ElementRef:
|
||||
value = new ElementRef(asElementData(view, nodeDef.index).renderElement);
|
||||
break;
|
||||
case QueryValueType.TemplateRef:
|
||||
value = createTemplateRef(view, nodeDef);
|
||||
break;
|
||||
case QueryValueType.ViewContainerRef:
|
||||
value = createViewContainerRef(view, nodeDef);
|
||||
break;
|
||||
case QueryValueType.Provider:
|
||||
value = asProviderData(view, nodeDef.index).instance;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user