0

我在理解指令屬性 vs 範圍變量傳遞給指令時遇到一些困難。
我正在制定一個動態加載正確模板的指令,具體取決於內容類型。 當我使用linker功能,使用範圍變量做切換的事情工作良好。動態模板和範圍變量

如果我使用:

<mydirective ng-repeat="item in items" content="item" type="item.type"></mydirective> 

我通過包含數據的對象content用於填充模板和該對象內我有一個type屬性我使用用於選擇的模板。
這是我的指令定義(一些代碼省略):

//[...] 
linker = function(scope, element, attrs){ 
    //templates is a service I use to retrieve the templates 
    loaderPromise = templates.getTemplate(scope.content.type) 
    promise = loaderPromise.success(function(html){ 
     element.html(html) 
    }).then(function(response){ 
     element.replaceWith($compile(element.html())(scope)) 
    }) 
} 

return { 
    restrict : "E", 
    replace: true, 
    scope: { 
     'content': "=" 
    }, 
    link : function(scope, element, attributes){ 
     linker(scope, element, attributes) 
    } 
    //[...] 
} 

現在,而不是這個,我想一個函數傳遞給「templateUrl」,像這樣:

return { 
    restrict : "E", 
    replace: true, 
    scope: { 
     'content': "=" 
    }, 
    templateUrl : function(element, attributes) { 
     // I don't access to the scope but only to the attributes 
     attributes.$observe(attributes.content.type, function(value){ 
     if(value) { 
      // templates is a service 
      return templates.getTemplateUrl(value.type) 
     } 
     }) 
    } 
    //[...] 
} 

現在,這將不起作用要麼我觀察attributes.content.typeattributes.type。這些屬性將始終爲undefined

我也嘗試添加傳遞給該指令type爲範圍變量:

scope: { 
     'content': "=" 
     'type': '=' 
     } 

但被繼續undefined

所以基本上我真的很困惑的使用attributes VS使用variable scopes

編輯:

我猜它是與NG-重複。如果我把一個斷點上線

attributes.$observe(attributes.content.type, function(value){ 

,我檢查attributes值我得到

$$element: jQuery.fn.init[1] 
$attr: Object 
content: "item" 
ngRepeat: ""item in items" 

,所以我想content尚未進行評估,這就是爲什麼attributes.content.typeundefined。想知道爲什麼..

回答

2

您的templates服務是同步的還是異步的? templateUrl函數必須返回一個表示Url的字符串,並且不會支持返回一個promise(爲了確保,我必須在Plunker中測試它)。

如果它同步返回一個字符串,那麼我不知道爲什麼attributes.type === undefined

類似以下工作:

templateUrl : function(element, attributes) { 
    return attributes.type; 
} 

我(稍微修改後的版本),你的代碼試了一下,它工作得很好 - 這裏的plunker

至於你的問題,使用scope因爲當你實現單向(即一個指令反應值的變化)或雙向綁定(即一個指令發生反應,並在父範圍變更的值)。使用屬性作爲初始化值。

編輯︰ 我現在更好地理解這個問題。這裏有幾件事情:應插分配給type屬性

的值(即在大括號):

<mydirective ng-repeat="item in items" content="item.content" type="{{item.type}}"></mydirective> 

,因爲你需要的插值字符串值,而不是對象(除非在範圍定義中將其定義爲"=type"),您也不會獲得該對象。

不幸的是,您將不幸在templateUrl函數中遇到問題,這與ng-repeat無關。這是因爲這些值尚未在templateUrl函數或compile函數中進行插值,所以您將獲得「{{item.type}}」作爲字符串。這對使用$interpolate服務也沒有幫助,因爲您還沒有合適的範圍。爲解決這一

一種方式是追加和$compile<div ng-include>在指向您所要求的模板鏈接功能:

link: function(scope, elem, attr){ 
    var template = attr.type || "template1"; 
    var templateUrl = template + ".html"; 
    elem.append("<div ng-include='\"" + templateUrl + "\"'></ng-include>"); 

    $compile(elem.contents())(scope); 
}, 

下面是完整的plunker

+0

我的'模板'服務是同步的。我已經更新了這個問題,我想這與ng-repeat更相關,但並非100%肯定。 – Leonardo 2014-10-05 14:55:58

+0

@Leonardo,我編輯了答案 – 2014-10-06 15:38:20

+0

所以基本上你的最後一個解決方案看起來與我的第一個解決方案非常相似一個工作),不是嗎? – Leonardo 2014-10-22 13:34:14