feat(upgrade): allow non-element selectors for downgraded components (#14037)
This affects the dynamic version of `upgrade` and makes it more consistent with the static version, while removing an artificial limitation. This commit also refactors the file layout and code, in order to share code wrt to dowgrading components between the dynamic and static versions.
This commit is contained in:

committed by
Miško Hevery

parent
1f90f29369
commit
9aafdc7b02
@ -44,4 +44,4 @@ export class PropertyBinding {
|
||||
this.bindAttr = `bind${capitalAttr}`;
|
||||
this.bindonAttr = `bindon${capitalAttr}`;
|
||||
}
|
||||
}
|
||||
}
|
@ -8,9 +8,8 @@
|
||||
|
||||
import {ComponentFactory, ComponentFactoryResolver, Injector, Type} from '@angular/core';
|
||||
|
||||
import * as angular from '../common/angular1';
|
||||
import {$INJECTOR, $PARSE, INJECTOR_KEY, REQUIRE_NG_MODEL} from '../common/constants';
|
||||
|
||||
import * as angular from './angular1';
|
||||
import {$INJECTOR, $PARSE, INJECTOR_KEY, REQUIRE_NG_MODEL} from './constants';
|
||||
import {DowngradeComponentAdapter} from './downgrade_component_adapter';
|
||||
|
||||
let downgradeCount = 0;
|
@ -8,11 +8,10 @@
|
||||
|
||||
import {ChangeDetectorRef, ComponentFactory, ComponentRef, EventEmitter, Injector, OnChanges, ReflectiveInjector, SimpleChange, SimpleChanges, Type} from '@angular/core';
|
||||
|
||||
import * as angular from '../common/angular1';
|
||||
import {$SCOPE} from '../common/constants';
|
||||
import * as angular from './angular1';
|
||||
import {hookupNgModel} from '../common/util';
|
||||
|
||||
import {ComponentInfo, PropertyBinding} from './component_info';
|
||||
import {$SCOPE} from './constants';
|
||||
|
||||
const INITIAL_VALUE = {
|
||||
__UNINITIALIZED__: true
|
@ -9,63 +9,32 @@
|
||||
import {DirectiveResolver} from '@angular/compiler';
|
||||
import {Directive, Type} from '@angular/core';
|
||||
|
||||
import {PropertyBinding} from '../common/component_info';
|
||||
|
||||
|
||||
const COMPONENT_SELECTOR = /^[\w|-]*$/;
|
||||
const SKEWER_CASE = /-(\w)/g;
|
||||
const directiveResolver = new DirectiveResolver();
|
||||
|
||||
export interface AttrProp {
|
||||
prop: string;
|
||||
attr: string;
|
||||
bracketAttr: string;
|
||||
bracketParenAttr: string;
|
||||
parenAttr: string;
|
||||
onAttr: string;
|
||||
bindAttr: string;
|
||||
bindonAttr: string;
|
||||
}
|
||||
|
||||
export interface ComponentInfo {
|
||||
type: Type<any>;
|
||||
selector: string;
|
||||
inputs?: AttrProp[];
|
||||
outputs?: AttrProp[];
|
||||
inputs?: PropertyBinding[];
|
||||
outputs?: PropertyBinding[];
|
||||
}
|
||||
|
||||
export function getComponentInfo(type: Type<any>): ComponentInfo {
|
||||
const resolvedMetadata: Directive = directiveResolver.resolve(type);
|
||||
let selector = resolvedMetadata.selector;
|
||||
if (!selector.match(COMPONENT_SELECTOR)) {
|
||||
throw new Error('Only selectors matching element names are supported, got: ' + selector);
|
||||
}
|
||||
selector = selector.replace(
|
||||
SKEWER_CASE, (all: any /** TODO #9100 */, letter: string) => letter.toUpperCase());
|
||||
const selector = resolvedMetadata.selector;
|
||||
|
||||
return {
|
||||
type: type,
|
||||
selector: selector,
|
||||
type,
|
||||
selector,
|
||||
inputs: parseFields(resolvedMetadata.inputs),
|
||||
outputs: parseFields(resolvedMetadata.outputs)
|
||||
};
|
||||
}
|
||||
|
||||
export function parseFields(names: string[]): AttrProp[] {
|
||||
const attrProps: AttrProp[] = [];
|
||||
if (names) {
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const parts = names[i].split(':');
|
||||
const prop = parts[0].trim();
|
||||
const attr = (parts[1] || parts[0]).trim();
|
||||
const capitalAttr = attr.charAt(0).toUpperCase() + attr.substr(1);
|
||||
attrProps.push(<AttrProp>{
|
||||
prop: prop,
|
||||
attr: attr,
|
||||
bracketAttr: `[${attr}]`,
|
||||
parenAttr: `(${attr})`,
|
||||
bracketParenAttr: `[(${attr})]`,
|
||||
onAttr: `on${capitalAttr}`,
|
||||
bindAttr: `bind${capitalAttr}`,
|
||||
bindonAttr: `bindon${capitalAttr}`
|
||||
});
|
||||
}
|
||||
}
|
||||
return attrProps;
|
||||
export function parseFields(bindings: string[]): PropertyBinding[] {
|
||||
return (bindings || []).map(binding => new PropertyBinding(binding));
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ export class UpgradeAdapter {
|
||||
* @internal
|
||||
*/
|
||||
private ng1ComponentsToBeUpgraded: {[name: string]: UpgradeNg1ComponentAdapterBuilder} = {};
|
||||
private providers: Provider[] = [];
|
||||
private upgradedProviders: Provider[] = [];
|
||||
private ngZone: NgZone;
|
||||
private ng1Module: angular.IModule;
|
||||
private moduleRef: NgModuleRef<any> = null;
|
||||
@ -437,11 +437,11 @@ export class UpgradeAdapter {
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
public upgradeNg1Provider(name: string, options?: {asToken: any}) {
|
||||
upgradeNg1Provider(name: string, options?: {asToken: any}) {
|
||||
const token = options && options.asToken || name;
|
||||
this.providers.push({
|
||||
this.upgradedProviders.push({
|
||||
provide: token,
|
||||
useFactory: (ng1Injector: angular.IInjectorService) => ng1Injector.get(name),
|
||||
useFactory: ($injector: angular.IInjectorService) => $injector.get(name),
|
||||
deps: [$INJECTOR]
|
||||
});
|
||||
}
|
||||
@ -557,7 +557,7 @@ export class UpgradeAdapter {
|
||||
providers: [
|
||||
{provide: $INJECTOR, useFactory: () => ng1Injector},
|
||||
{provide: $COMPILE, useFactory: () => ng1Injector.get($COMPILE)},
|
||||
this.providers
|
||||
this.upgradedProviders
|
||||
],
|
||||
imports: [this.ng2AppModule]
|
||||
}).Class({
|
||||
|
Reference in New Issue
Block a user