2017-07-26 49 views
2

說我有一個深度嵌套的對象圖,我結合:創建角模板本地綁定上下文

<div>{{model.rootProperty}}</div> 

<div> 
    <div>{{model.some.deeply.nested.property.with.a.donut.name}}</div> 
    <div>{{model.some.deeply.nested.property.with.a.donut.calories}}</div> 
    <div>{{model.some.deeply.nested.property.with.a.donut.deliciousness}}</div> 
</div> 

我不想重複存取的那鏈。我知道我可以在我的viewmodel上公開一個屬性,但我更喜歡用某種方式來創建本地上下文。我想要的語法會是這樣的:

<div>{{model.rootProperty}}</div> 

<div [binding-context]="model.some.deeply.nested.property.with.a.donut"> 
    <div>{{name}}</div> 
    <div>{{calories}}</div> 
    <div>{{deliciousness}}</div> 
</div> 

我會怎麼做呢?

我嘗試創建一個組件,其模板僅包含<ng-content></ng-content>,但以這種方式跨越的內容仍具有組件的父組件的上下文。

我知道我可以換一個<template>內的內容和我的組件使用模板的出口,但是這不是我寧願更多的標記,似乎*ngFor不需要這個。

這可能嗎?

+0

看起來像一個更簡單的解決方案是與「計劃A」,並添加一個屬性到您的視圖/模型。畢竟這是它的目的。 :-) – DeborahK

+0

是的,但我覺得如果我的別名在模板中顯式存在,它會更具可讀性/可維護性。有時候這個模式可以嵌套,我想引用嵌套屬性的一些嵌套屬性,並且有多個viewmodel屬性不會使模板中的關係可見。 – Mud

+0

是的,你需要將你的html包裝在'ng-template'中才能做到這一點 –

回答

2

它可以定義類似於* ngIf和* ngFor稱爲結構指令*的BindingContext:

<div *bindingContext = "let a_variable be an_expression"> 

角度做了很多與此語法幕後法寶。首先,星號創建一個< ng-template >立即使用。然後評估微語法並調用一個名爲bindingContextBe的指令。該指令使得an_expression可作爲$implicit模板背景下,這反過來又被分配到a_variable

有一個在Angular documentation充分的解釋。

我實現的BindingContext如下:

import {Directive, EmbeddedViewRef, Input, 
     TemplateRef, ViewContainerRef} from '@angular/core'; 

@Directive({selector: '[bindingContextBe]'}) 
export class BindingContextDirective { 
    private context = new BindingContextDirectiveContext(); 
    private viewRef: EmbeddedViewRef<BindingContextDirectiveContext>|null = null; 

    constructor(private viewContainer: ViewContainerRef, 
     private templateRef: TemplateRef<BindingContextDirectiveContext>) { 
    } 

    @Input() 
    set bindingContextBe(context: any) { 
    this.context.$implicit = context; 
    if (!this.viewRef) { 
     this.viewContainer.clear(); 
     this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef, 
                  this.context); 
    } 
    } 
} 

export class BindingContextDirectiveContext { 
    public $implicit: any = null; 
} 

用例:

Full: 

<div> 
    <div>{{model.some.deeply.nested.property.with.a.donut.name}}</div> 
    <div>{{model.some.deeply.nested.property.with.a.donut.calories}}</div> 
    <div>{{model.some.deeply.nested.property.with.a.donut.deliciousness}}</div> 
    <input [(ngModel)]="model.some.deeply.nested.property.with.a.donut.name"> 
</div> 

<hr> 

Alias: 

<div *bindingContext="let food be model.some.deeply.nested.property.with.a.donut"> 
    <div>{{food.name}}</div> 
    <div>{{food.calories}}</div> 
    <div>{{food.deliciousness}}</div> 
    <input [(ngModel)]="food.name"> 
</div> 

PS:不要忘了申報指揮你的模塊中。