feat(upgrade): use ComponentFactory.inputs/outputs/ngContentSelectors
(#15214)
DEPRECATION: - the arguments `inputs` / `outputs` / `ngContentSelectors` of `downgradeComponent` are no longer used as Angular calculates these automatically now. - Compiler.getNgContentSelectors is deprecated. Use ComponentFactory.ngContentSelectors instead.
This commit is contained in:

committed by
Miško Hevery

parent
791534f2f4
commit
9429032da1
@ -9,9 +9,8 @@
|
||||
import {ChangeDetectorRef, ComponentFactory, ComponentRef, EventEmitter, Injector, OnChanges, ReflectiveInjector, SimpleChange, SimpleChanges, Type} from '@angular/core';
|
||||
|
||||
import * as angular from './angular1';
|
||||
import {ComponentInfo, PropertyBinding} from './component_info';
|
||||
import {PropertyBinding} from './component_info';
|
||||
import {$SCOPE} from './constants';
|
||||
import {NgContentSelectorHelper} from './ng_content_selector_helper';
|
||||
import {getAttributesAsArray, getComponentName, hookupNgModel} from './util';
|
||||
|
||||
const INITIAL_VALUE = {
|
||||
@ -27,7 +26,7 @@ export class DowngradeComponentAdapter {
|
||||
private changeDetector: ChangeDetectorRef = null;
|
||||
|
||||
constructor(
|
||||
private id: string, private info: ComponentInfo, private element: angular.IAugmentedJQuery,
|
||||
private id: string, private element: angular.IAugmentedJQuery,
|
||||
private attrs: angular.IAttributes, private scope: angular.IScope,
|
||||
private ngModel: angular.INgModelController, private parentInjector: Injector,
|
||||
private $injector: angular.IInjectorService, private $compile: angular.ICompileService,
|
||||
@ -67,9 +66,9 @@ export class DowngradeComponentAdapter {
|
||||
|
||||
setupInputs(): void {
|
||||
const attrs = this.attrs;
|
||||
const inputs = this.info.inputs || [];
|
||||
const inputs = this.componentFactory.inputs || [];
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
const input = new PropertyBinding(inputs[i]);
|
||||
const input = new PropertyBinding(inputs[i].propName, inputs[i].templateName);
|
||||
let expr: any /** TODO #9100 */ = null;
|
||||
|
||||
if (attrs.hasOwnProperty(input.attr)) {
|
||||
@ -103,7 +102,7 @@ export class DowngradeComponentAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
const prototype = this.info.component.prototype;
|
||||
const prototype = this.componentFactory.componentType.prototype;
|
||||
if (prototype && (<OnChanges>prototype).ngOnChanges) {
|
||||
// Detect: OnChanges interface
|
||||
this.inputChanges = {};
|
||||
@ -118,9 +117,9 @@ export class DowngradeComponentAdapter {
|
||||
|
||||
setupOutputs() {
|
||||
const attrs = this.attrs;
|
||||
const outputs = this.info.outputs || [];
|
||||
const outputs = this.componentFactory.outputs || [];
|
||||
for (let j = 0; j < outputs.length; j++) {
|
||||
const output = new PropertyBinding(outputs[j]);
|
||||
const output = new PropertyBinding(outputs[j].propName, outputs[j].templateName);
|
||||
let expr: any /** TODO #9100 */ = null;
|
||||
let assignExpr = false;
|
||||
|
||||
@ -158,7 +157,7 @@ export class DowngradeComponentAdapter {
|
||||
});
|
||||
} else {
|
||||
throw new Error(
|
||||
`Missing emitter '${output.prop}' on component '${getComponentName(this.info.component)}'!`);
|
||||
`Missing emitter '${output.prop}' on component '${getComponentName(this.componentFactory.componentType)}'!`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,49 +182,31 @@ export class DowngradeComponentAdapter {
|
||||
}
|
||||
|
||||
groupProjectableNodes() {
|
||||
const ngContentSelectorHelper =
|
||||
this.parentInjector.get(NgContentSelectorHelper) as NgContentSelectorHelper;
|
||||
const ngContentSelectors = ngContentSelectorHelper.getNgContentSelectors(this.info);
|
||||
|
||||
if (!ngContentSelectors) {
|
||||
throw new Error('Expecting ngContentSelectors for: ' + getComponentName(this.info.component));
|
||||
}
|
||||
|
||||
return this._groupNodesBySelector(ngContentSelectors, this.element.contents());
|
||||
}
|
||||
|
||||
/**
|
||||
* Group a set of DOM nodes into `ngContent` groups, based on the given content selectors.
|
||||
*/
|
||||
private _groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] {
|
||||
const projectableNodes: Node[][] = [];
|
||||
let wildcardNgContentIndex: number;
|
||||
|
||||
for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) {
|
||||
projectableNodes[i] = [];
|
||||
}
|
||||
|
||||
for (let j = 0, jj = nodes.length; j < jj; ++j) {
|
||||
const node = nodes[j];
|
||||
const ngContentIndex = findMatchingNgContentIndex(node, ngContentSelectors);
|
||||
if (ngContentIndex != null) {
|
||||
projectableNodes[ngContentIndex].push(node);
|
||||
}
|
||||
}
|
||||
|
||||
return projectableNodes;
|
||||
let ngContentSelectors = this.componentFactory.ngContentSelectors;
|
||||
return groupNodesBySelector(ngContentSelectors, this.element.contents());
|
||||
}
|
||||
}
|
||||
|
||||
let _matches: (this: any, selector: string) => boolean;
|
||||
/**
|
||||
* Group a set of DOM nodes into `ngContent` groups, based on the given content selectors.
|
||||
*/
|
||||
export function groupNodesBySelector(ngContentSelectors: string[], nodes: Node[]): Node[][] {
|
||||
const projectableNodes: Node[][] = [];
|
||||
let wildcardNgContentIndex: number;
|
||||
|
||||
function matchesSelector(el: any, selector: string): boolean {
|
||||
if (!_matches) {
|
||||
const elProto = <any>Element.prototype;
|
||||
_matches = elProto.matchesSelector || elProto.mozMatchesSelector || elProto.msMatchesSelector ||
|
||||
elProto.oMatchesSelector || elProto.webkitMatchesSelector;
|
||||
for (let i = 0, ii = ngContentSelectors.length; i < ii; ++i) {
|
||||
projectableNodes[i] = [];
|
||||
}
|
||||
return _matches.call(el, selector);
|
||||
|
||||
for (let j = 0, jj = nodes.length; j < jj; ++j) {
|
||||
const node = nodes[j];
|
||||
const ngContentIndex = findMatchingNgContentIndex(node, ngContentSelectors);
|
||||
if (ngContentIndex != null) {
|
||||
projectableNodes[ngContentIndex].push(node);
|
||||
}
|
||||
}
|
||||
|
||||
return projectableNodes;
|
||||
}
|
||||
|
||||
function findMatchingNgContentIndex(element: any, ngContentSelectors: string[]): number {
|
||||
@ -247,4 +228,15 @@ function findMatchingNgContentIndex(element: any, ngContentSelectors: string[]):
|
||||
ngContentIndices.push(wildcardNgContentIndex);
|
||||
}
|
||||
return ngContentIndices.length ? ngContentIndices[0] : null;
|
||||
}
|
||||
}
|
||||
|
||||
let _matches: (this: any, selector: string) => boolean;
|
||||
|
||||
function matchesSelector(el: any, selector: string): boolean {
|
||||
if (!_matches) {
|
||||
const elProto = <any>Element.prototype;
|
||||
_matches = elProto.matches || elProto.matchesSelector || elProto.mozMatchesSelector ||
|
||||
elProto.msMatchesSelector || elProto.oMatchesSelector || elProto.webkitMatchesSelector;
|
||||
}
|
||||
return el.nodeType === Node.ELEMENT_NODE ? _matches.call(el, selector) : false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user