我得到错误:“组件视图上的意外指令值'未定义'”当我将多态组件放在单独的文件中时,但当它们都在同一个文件中时没有错误。 我已经研究了关于这个错误的所有SO问题无济于事,但是因为我有一个工作和非工作的场景,希望有一些ng2 /打字员大师可以帮助我把它排除在外:
我把问题归结为玩具场景,我有复合天体(星系,太阳系,星星)。任何天体都可以包含任何其他天体。我知道 - 有些人可能会说明星不能包含星系,但他们可能从未看过Dr. Who。 : - )
我的主要组件设置描述符并创建顶级组件,在本例中是一个星系:
import {Component} from 'angular2/core';
import {CelestialObject} from './CelestialObject';
@Component({
selector: 'preview',
directives: [CelestialObject],
template: `
<celestial-object [descriptor]="descriptor"></celestial-object>
`
})
export class MainComponent {
private descriptor;
constructor() {
this.descriptor = {
type: 'galaxy',
children: [
{ type: 'solarSystem', children: [{type: 'star', children: []}] },
{ type: 'star', children: []}
]
};
}
}
CelestialObjects.ts:
import {Component, Input, DynamicComponentLoader, ElementRef, AfterViewInit} from 'angular2/core';
@Component({
selector: 'celestial-object',
template: `
<span #loadSpecificCelestialObjectHere></span>
`
})
export class CelestialObject implements AfterViewInit {
@Input() descriptor: any;
constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) { /* */
}
ngAfterViewInit() {
let objectType: any = null;
switch (this.descriptor.type) {
case 'solarSystem':
objectType = SolarSystem;
break;
case 'galaxy':
objectType = Galaxy;
break;
case 'star':
objectType = Star;
break;
}
this.dcl.loadIntoLocation(objectType, this.elementRef, 'loadSpecificCelestialObjectHere').then((comp) => {
comp.instance.descriptor = this.descriptor;
});
}
}
//======================================
// Galaxy
//======================================
@Component({
selector: 'galaxy',
directives: [CelestialObject],
template: `
<p>Galaxy</p>
<celestial-object [descriptor]="obj" *ngFor="#obj of descriptor.children"></celestial-object>
`
})
export class Galaxy {
@Input() descriptor: any;
}
//======================================
// SolarSystem
//======================================
@Component({
selector: 'solar-system',
directives: [CelestialObject],
template: `
<p>Solar system</p>
<celestial-object [descriptor]="obj" *ngFor="#obj of descriptor.children"></celestial-object>
`
})
export class SolarSystem {
@Input() descriptor: any;
}
//======================================
// Star
//======================================
@Component({
selector: 'star',
directives: [CelestialObject],
template: `
<p>Star</p>
<celestial-object [descriptor]="obj" *ngFor="#obj of descriptor.children"></celestial-object>
`
})
export class Star {
@Input() descriptor: any;
}
CelestialObjectsMinusGalaxy.ts:
import {Component, Input, DynamicComponentLoader, ElementRef, AfterViewInit} from 'angular2/core';
import {Galaxy} from './Galaxy';
@Component({
selector: 'celestial-object',
template: `
<span #loadSpecificCelestialObjectHere></span>
`
})
export class CelestialObject implements AfterViewInit {
@Input() descriptor: any;
constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) { /* */
}
ngAfterViewInit() {
let objectType: any = null;
switch (this.descriptor.type) {
case 'solarSystem':
objectType = SolarSystem;
break;
case 'galaxy':
objectType = Galaxy;
break;
case 'star':
objectType = Star;
break;
}
this.dcl.loadIntoLocation(objectType, this.elementRef, 'loadSpecificCelestialObjectHere').then((comp) => {
comp.instance.descriptor = this.descriptor;
});
}
}
//======================================
// SolarSystem
//======================================
@Component({
selector: 'solar-system',
directives: [CelestialObject],
template: `
<p>Solar system</p>
<celestial-object [descriptor]="obj" *ngFor="#obj of descriptor.children"></celestial-object>
`
})
export class SolarSystem {
@Input() descriptor: any;
}
//======================================
// Star
//======================================
@Component({
selector: 'star',
directives: [CelestialObject],
template: `
<p>Star</p>
<celestial-object [descriptor]="obj" *ngFor="#obj of descriptor.children"></celestial-object>
`
})
export class Star {
@Input() descriptor: any;
}
和Galaxy.ts。与以前相同的代码,只需拆分成单独的文件并导入CelestialObject:
import {Component, Input} from 'angular2/core';
import {CelestialObject} from './CelestialObject';
//======================================
// Galaxy
//======================================
@Component({
selector: 'galaxy',
directives: [CelestialObject],
template: `
<p>Galaxy</p>
<celestial-object [descriptor]="obj" *ngFor="#obj of descriptor.children"></celestial-object>
`
})
export class Galaxy {
@Input() descriptor: any;
}
现在我收到了错误。我意识到这最终成为一个循环引用,但是没有办法将这些组件保存在自己的文件中,而不会在组件视图中出现“Unexpected directive value'undefined'错误?”
任何帮助非常感谢。这是一只要解开的熊。
答案 0 :(得分:1)
您可以尝试删除类型开关并将其替换为事件发射器
在CelestialObject
:
export class CelestialObject implements AfterViewInit {
@Input() descriptor: any;
constructor(private dcl: DynamicComponentLoader,
private emitter: SharedEmitterService,
private elementRef: ElementRef) { /* */
this.emitter.subscribe(objectType => load(objectType));
}
load(objectType) {
this.dcl.loadIntoLocation(objectType, this.elementRef, 'loadSpecificCelestialObjectHere').then((comp) => {
comp.instance.descriptor = this.descriptor;
});
}
}
然后在您的其他课程中,您可以启动加载:
export class Galaxy {
@Input() descriptor: any;
constructor(private emitter: SharedEmitterService) { /* */ }
ngOnInit() {
this.emitter.emit(Galaxy);
}
}
答案 1 :(得分:1)
问题是Galaxy导入CelestialObject和CelestialObject导入Galaxy。 Sasxa建议摆脱switch语句,从而使CelestialObject免于依赖Galaxy。
这导致了使用实际类型填充描述符的解决方案,而不是表示类型的字符串:
DELETE FROM TableA where MLS NOT IN (SELECT LIST_3 FROM TableB) LIMIT 100;
然后CelestialObject变为以下内容,不依赖于特定的天体:
import {Component} from 'angular2/core';
import {CelestialObject} from './CelestialObject';
import {Galaxy} from './Galaxy';
import {SolarSystem} from './SolarSystem';
import {Star} from './Star';
@Component({
selector: 'preview',
directives: [CelestialObject],
template: `
<celestial-object [descriptor]="descriptor"></celestial-object>
`
})
export class MainComponent {
private descriptor;
constructor() {
this.descriptor = {
type: Galaxy,
children: [
{ type: SolarSystem, children: [{type: Star, children: []}] },
{ type: Star, children: []}
]
};
}
}
感谢Sasxa提供关键的拼图。