2016-05-09 59 views
0

我正在使用AngularJS 1.5.3。我有一個用例,我從另一個指令中調用一個指令。換句話說,指令是鏈接的。我希望我的外部指令的範圍變量根據內部指令的結果進行更新。我在這裏創建了一個JSFiddle:http://jsfiddle.net/gstanek/6voytwuc/30/,它顯示了我所嘗試的內容。AngularJS:指令與模板引用指令和數據綁定

相同的代碼在這裏重現:

<div ng-app="myApp" ng-controller="MyCtrl"> 
    <span first-layer-directive first-layer-info="'fist layer text'"></span> 
</div> 

var myApp = angular.module('myApp', []); 

myApp.controller('MyCtrl', function($scope) { 

}); 

myApp.directive('firstLayerDirective', function() { 
    return { 
     scope: { 
      firstLayerInfo: '=' 
     }, 
     template: "<div><span>1st Layer Displayed info='{{firstLayerDisplay}}'</span></div>" + 
     "<div>" + 
     "<span second-layer-directive second-layer-info=\"'second layer text'\" info=\"info\">Second layer displayed info='{{secondLayerDisplay}}'</span></div>" + "<span>Info returned from 2nd layer: {{info}}</span>", 
     link: function (scope, element, attrs) { 
      scope.firstLayerDisplay = scope.firstLayerInfo; 
      scope.info = ''; 
     } 
    }; 
}); 

myApp.directive('secondLayerDirective', function() { 
    return { 
     scope: { 
      secondLayerInfo: '=', 
      info: '=' 
     }, 
     template: "<div><span>2nd Layer Displayed info='{{secondLayerDisplay}}'</span></div>", 
     link: function (scope, element, attrs) { 
      scope.secondLayerDisplay = scope.secondLayerInfo + ' plus more info'; 
      scope.info='info generated in 2nd layer'; 
     } 
    }; 
}); 

運行此的jsfiddle的輸出是:

1st Layer Displayed info='fist layer text' 
2nd Layer Displayed info='second layer text plus more info' 
Info returned from 2nd layer: 

相反,我想最後一行顯示如下: Info returned from 2nd layer: info generated in 2nd layer

如何將數據從內部指令傳遞迴外部直接並確保使用新值更新外部指令?

回答

2

您可以從外部指令訪問內部指令的範圍。所以只需從firstLayerDirective的鏈接功能中刪除。

scope.info = ''; 

如果我明白你的問題是正確的,你將通過這樣做得到你的結果。

+0

這似乎解決了所描述的問題,但我仍然想知道爲什麼。如果外部指令確實看到內部指令的範圍,並且在內部指令中更新了'scope.info',爲什麼即使當'scope.info'初始設置爲a時,它也不會在外部指令中更新空白字符串?謝謝! – Gabe

+0

在你的情況下,你已經定義了鏈接功能。你沒有提到前鏈接或後鏈接,所以它作爲後鏈接功能。因此,「secondLayerDirective」的鏈接功能將首先執行,然後執行「firstLayerDirective」的鏈接功能。所以最後scope.info將設置爲空白。還有一件事你正在使用隔離範圍,它不像一次性綁定。每當父指令更改該值時,子指令就會獲得更改。 –

+0

謝謝!這爲我清除它 – Gabe

1

UPDATE 正如OP指出的那樣,原始解決方案「有效」,但實際上並不正確。我相信這種情況發生的原因是因爲內嵌模板與鏈接函數一起編譯的方式。如果您更改鏈接功能以使用預鏈接,它似乎工作。

link: { 
      pre: function (scope, element, attrs) { 
      scope.firstLayerDisplay = scope.firstLayerInfo; 
      scope.info = ''; 
      } 
     } 

原來的答案

爲了解決這個問題,你需要使用所謂的 「點號」(見這裏解釋http://jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html)。

如果你改變你的父母的指令看起來像下面的代碼,它應該解決你看到的問題......

myApp.directive('firstLayerDirective', function() { 
    return { 
     scope: { 
      firstLayerInfo: '=' 
     }, 
     template: "<div><span>1st Layer Displayed info='{{firstLayerDisplay}}'</span></div>" + 
     "<div>" + 
     "<span second-layer-directive second-layer-info=\"'second layer text'\" info=\"info.text\">Second layer displayed info='{{secondLayerDisplay}}'</span></div>" + "<span>Info returned from 2nd layer: {{info}}</span>", 
     link: function (scope, element, attrs) { 
      scope.firstLayerDisplay = scope.firstLayerInfo; 
      scope.info.text = ''; 
     } 
    }; 
}); 

我做了改變「scope.info =‘’」,以唯一的變化「scope.info.text =''」然後將「info.text」傳遞給html中的子指令。

讓我知道如果您有任何問題。

+0

您指出的更改確實可以解決觀察到的問題,但我不認爲它們是因爲點符號模式而解決的。相反,試圖在'firstLayerDirective'中設置'scope.into.text'導致初始化錯誤:'angular.js:13424 TypeError:無法設置未定義的屬性'文本'。該副作用使得變量未在「firstLayerDirective」中初始化,這導致了@HardikPatel提到的相同解決方案。如果我首先初始化,'scope.info = {};',然後設置文本:'scope.info.text ='';',問題仍然存在 – Gabe

+0

你說得對,我的壞!我想更新我的答案,因爲我認爲我找到了問題。它與鏈接功能和內聯模板有關。我認爲你需要在預鏈接中設置你的範圍變量,否則模板會在範圍設置之前被編譯,然後東西就會全部出來。 – sourdoughdetzel

+0

謝謝!我很感激你的意見,並且發佈了'pre'定義的代碼。鑑於@HardikPatel詳細介紹了所見行爲的原因,我已將他的答覆標記爲答案 – Gabe

0

你需要的是ng-transclude

我做給你一個例子,看看this

相同的代碼在這裏重現:

var myApp = angular.module('myApp', []); 
 

 
myApp.controller('MyCtrl', function($scope) { 
 
    $scope.foo = "I'm foo!"; 
 
    $scope.lines = []; 
 
    $scope.addLine = function() { 
 
     $scope.lines.push($scope.lines.length); 
 
    }; 
 
}); 
 

 
myApp.directive('firstLayerDirective', function() { 
 
    return { 
 
     scope: { 
 
      firstLayerInfo: '=' 
 
     }, 
 
     transclude:true, 
 
     template: "<div><span>1st Layer Displayed info='{{firstLayerDisplay}}'</span></div><div ng-transclude></div>", 
 
     link: function (scope, element, attrs) { 
 
      scope.firstLayerDisplay = scope.firstLayerInfo; 
 
      scope.info = ''; 
 
     } 
 
    }; 
 
}); 
 

 
myApp.directive('secondLayerDirective', function() { 
 
    return { 
 
     scope: { 
 
      secondLayerInfo: '=', 
 
      info: '=' 
 
     }, 
 
     template: "<div><span>2nd Layer Displayed info='{{secondLayerDisplay}}'</span></div>", 
 
     link: function (scope, element, attrs) { 
 
      scope.secondLayerDisplay = scope.secondLayerInfo + ' plus more info'; 
 
      scope.info='info generated in 2nd layer'; 
 
     } 
 
    }; 
 
});
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js"></script> 
 
<div ng-app="myApp" ng-controller="MyCtrl"> 
 
    <button ng-click="addLine()">Add a line</button> 
 
    <div ng-repeat="line in lines"> 
 
     I'm a new line. {{foo}} 
 
    </div> 
 
    <span first-layer-directive first-layer-info="'fist layer text'"> 
 
     <div><span second-layer-directive second-layer-info="'second layer text'" info="info">Second layer displayed info='{{secondLayerDisplay}}'</span></div><span>Info returned from 2nd layer: {{info}}</span> 
 
    </span> 
 
</div>

+0

感謝您的建議。在我的使用案例中,我寧願保持兩個範圍隔離,只傳回需要的信息。鑑於此,'ng-transclude'選項在我的大型用例中對我來說效果不佳。這從我的最初的問題不清楚,所以我感謝您的輸入 – Gabe