2017-12-28 3 views
1

アプリケーションレイアウトには、ツールバーと実際のコンテンツ領域があります。ツールバーは幾分複雑なDOM構造を持っているので、そこからコンポーネントを作成することにしました。テンプレートを動的に4/5の角度に配置する

我々は、各ページに、このコンポーネントを再利用できるが、ツールバーの位置は、(いくつかの他の成分が間にある)、実際のコンテンツの隣にはありません。したがって、親ページコンポーネントにツールバーを1回配置し、必要に応じて各ページにツールバーの内容を宣言するだけです。

我々は #tbcontentの内容を取り、 #toolbar内に置き、効果的にこのような何かレンダリングでしょう上の例ではこのように
<app> 
    <toolbar> 
     <ng-container #toolbar></ng-container> 
    </toolbar> 

    <some unrelated component>...</some unrelated component> 

    <content> 
     <ng-template #tbcontent> 
      <button>Click me!</button> 
     </ng-template> 
     <p>Actual page content!</p> 
    </content> 
</app> 

:我々は#toolbarとから#tbcontentノードの両方を照会しようとしている

<app> 
    <toolbar> 
     <button>Click me!</button> 
    </toolbar> 

    <some unrelated component>...</some unrelated component> 

    <content> 
     <p>Actual page content!</p> 
    </content> 
</app> 

をルートAppComponent@ViewChildを使用します(コードは分かりやすくするために簡略化されています)。

@Component({ 
    /* ... */ 
}) 
export class AppComponent implements OnInit, AfterViewInit { 
    @ViewChild("tbcontent") tbcontent: TemplateRef<any>; 
    @ViewChild("toolbar", {read: ViewContainerRef}) toolbar: ViewContainerRef; 

    /* ... */ 

    ngAfterViewInit() { 
     console.log('ngAfterViewInit'); 
     console.log(this.tbcontent); 
     console.log(this.toolbar); 
     this.toolbar.createEmbeddedView(this.tbcontent); 
    } 
} 

しかし両方の参考文献はundefinedです。要素に正しくアクセスする方法はありますか?これは実際には悪い習慣ですか、同じ結果を達成するためのより良い方法があるかもしれませんか?

アップデート:@マーティン-NUCの親切が、トリックを行うように思われ、*ngTemplateOutletを使用して提案した場合にのみ、同じコンポーネント内での生活をコピーされたノード。ここでは、このを示すJSFiddleです:

https://jsfiddle.net/carlosafonso/k3oq56oq/3/

ありがとうございました。

+0

'' また、コンポーネントのですか? –

+0

はい、それはかなりのダミーのものですが(たぶんタグを含んでいます)。 – cafonso

+0

' 'の外にテンプレートを定義できますか?念のために。私の答えを見てください。 –

答えて

0

テンプレートを定義すると、DOMに挿入されません。 DOMに挿入するには、いくつかのディレクティブを使用する必要があります。

またng-containerは、基本的には、いくつかのコンテンツのためだけのプレースホルダーですが、それはDOMにレンダリングされていません。私が何をやろうとしていること

<toolbar> 
    <ng-container *ngTemplateOutlet="tbcontent"></ng-container> 
</toolbar> 

EDITだと思う

:質問は、親コンポーネント内の子コンポーネントからテンプレートを表示する方法でした。私は基本的に子コンポーネントからの出力としてテンプレートを渡しました。ここでそれを達成する方法です。

親コンポーネント:

@Component({ 
    selector: 'app', 
    template: ` 
    <div class="container"> 
     <toolbar> 
     <ng-container *ngTemplateOutlet="toolbarContent"></ng-container>  
     </toolbar> 
     <hr/> 
     <content (toolbarLoaded)="displayToolbar($event)"></content> 
    </div> 
    `, 
}) 
class AppComponent { 

    constructor() { 
    } 

    displayToolbar($event) { 
    this.toolbarContent = $event; 
    } 
} 

子コンポーネントツールバーのテンプレートを使用して:

@Component({ 
    selector: 'content', 
    template: ` 
    <ng-template #tb> 
     <button type="button" class="btn btn-sm btn-primary">Content-specific action</button> 
    </ng-template> 
    <p>These are the page contents.</p> 
    ` 
}) 
class ContentComponent { 
    @Output() toolbarLoaded = new EventEmitter<any>(); 
    @ViewChild('tb') tb; 

    ngAfterViewInit() { 
    // arrow function dont work in jsfiddle somehow :(
    let that = this; 
    // we need timeout to avoid Expression had changed after it was checked (https://github.com/angular/angular/issues/6005) 
    setTimeout(() => { 
     that.toolbarLoaded.emit(that.tb); 
    }, 0); 
    } 
} 

Jsfiddle:https://jsfiddle.net/fdv1tesr/3/

+0

これは、 '#tbcontent'が' 'の中にある場合には動作しますが、それが兄弟コンポーネントの内部にある場合は機能しません。 私は実際の設定でこのフィドルを作成しました。'#tbcontent'ノードが' ' テンプレートに移動された場合、ボタンはツールバーに表示されません: https://jsfiddle.net/carlosafonso/k3oq56oq/2/ – cafonso

+0

@cafonso'ツールバーを親ページコンポーネントに入れて、必要に応じて各ページのツールバーの内容を宣言するだけです - 子コンポーネント( '')に 'tbcontent'を定義したいのですが、それを親コンポーネント ')? –

+0

はい、ツールバー内のボタンは表示されている実際のページに依存しているためです。 たとえば、ユーザーのリストには新しいユーザーを作成するボタンが表示されますが、新しいユーザーフォームに戻るボタンが表示されます。これは、私の意見では、ツールバーの内容を宣言することがコンテンツ自体の中で行われるべき理由です。 – cafonso

関連する問題