2016-04-15 29 views
3

我有三個嵌套的組件,叫做level0level1level2,定義如下所示:@ViewChild:接入盛大孩子的方法

@Component({ 
selector: 'level2', 
template: `<div>I am level 2</div>`, 
}) 
export class Level2 { 
    getName(){ 
    return "my name is 'TWO'"; 
    } 
} 

@Component({ 
selector: 'level1', 
template: `<div>I am level 1<level2></level2></div>`, 
directives: [Level2] 
}) 
export class Level1 { 
    getName(){ 
    return "my name is 'ONE'"; 
    } 
} 

@Component({ 
selector: 'level0', 
template: `<div>I am level 0<level1></level1></div>`, 
directives: [Level1,Level2] 
}) 
export class App { 
@ViewChild(Level1) level1:Level1; 
@ViewChild(Level2) level2:Level2; 
ngAfterViewInit() { 
    if(this.level1){var name1 = this.level1.getName();} 
    if(this.level2){var name2 = this.level2.getName();} 
    console.log("name1",name1); 
    console.log("name2",name2); 
    } 
} 

在控制檯,我預計會看到:

name1 my name is 'ONE' 
name2 my name is 'TWO' 

但我看到,而不是:

name1 my name is 'ONE' 
name2 undefined 

我缺少什麼?爲什麼Level0組件不能訪問Level2@ViewChild

有沒有辦法訪問Level0中的Level2方法?


Here is the plnkr

回答

3

我不認爲這是目前可能的。

ViewQueryMetadata API doc說以下內容:

支持相同的查詢參數QueryMetadata,除了後裔

QueryMetadata API doc有這樣的子孫例如:

配置查詢是否查找直接孩子或查詢元素的所有後代,通過使用後代參數。它默認設置爲false。

...這裏的代碼未顯示...

當查詢項目,第一個容器只能看到A和B的默認,但與Query(TextDirective, {descendants: true})會請參閱C了。

+0

好的,謝謝。我會研究'查詢(TextDirective,{descendants:true})'然後... – Manube

+2

@Manube,我想你會感到失望。我相信查詢不贊成ViewChild和ViewChildren。如果Query仍然存在,我不認爲它支持'後代'。 (在我回答這個問題之前,我試着在Plunker中稍微玩弄一下,但我無法完成它。) –

+0

對,然後我會嘗試不同的想法。因爲我希望實現一個應用程序,其中父母應該知道所有選定的嵌套後代,我想我會保留服務中的數據並將它們注入父代 – Manube

4

如果使用ViewChild在你的嵌套組件的每一層,像這種方式可以來達到的:

// Level 2 
@Component({ 
selector: 'level2', 
template: `<div>I am level 2</div>`, 
}) 
export class Level2 { 
    getName(){ 
    return "my name is 'TWO'"; 
    } 
} 


// Level 1 
@Component({ 
selector: 'level1', 
template: `<div>I am level 1<level2></level2></div>`, 
directives: [Level2] 
}) 
export class Level1 { 
    @ViewChild(Level2) level2:Level2; 
    getName(){ 
    return "my name is 'ONE'"; 
    } 

    // You need to add additional function that would be called from level 1 
    calledFromLevel1() { 
    return this.level2.getName(); 
    } 
} 


// Level 0 
@Component({ 
selector: 'level0', 
template: `<div>I am level 0<level1></level1></div>`, 
directives: [Level1,Level2] 
}) 
export class App { 
@ViewChild(Level1) level1:Level1; 
ngAfterViewInit() { 
    if(this.level1) { 
    var name1 = this.level1.getName(); 
    var name2 = this.level1.calledFromLevel1(); 
    } 
    console.log("name1",name1); 
    console.log("name2",name2); 
    } 
}