1

我試圖在我的應用程序中動態插入ng-options指令,這些指令都在<select>之間,它們都有自己的類名和其他指令(如ng-if等)。Dynamic AngularJS指令

<div ng-app="app" ng-controller="ctrl"> 
    <select ng-model="model" class="myClass" ng-if="condition || true" my-directive> 
    </select> 
    <pre>{{ model | json }}</pre> 
</div> 

angular 
.module('app', []) 
.directive('myDirective', function($compile) { 
    return { 
    restrict: 'A', 
    scope: false, 
    link: function($scope, $elem, $attr) { 
     $scope.items = [{ label: "foo", value: "foofoo"}, 
         { label: "bar", value: "barbar"}]; 
     $elem.removeAttr('my-directive'); // Prevents infinite loop 
     $elem.attr('ng-options', 'item as item.label for item in items'); 
     $compile($elem)($scope); 
    } 
    } 
}) 
.controller('ctrl', function($scope) { 
    $scope.model = null; 
    $scope.$watch('model', function(val) { console.log('•', val) }); 
}); 

Codepen

的想法是,my-directive應該由ng-options更換和元素還是應該表現得像正常,應用到它的所有其他指令。

我不明白爲什麼ng-model沒有得到更新,因爲指令的作用域是父作用域(scope: false)。我試圖在指令的compile步驟中對DOM進行修改,但$scope.items未知,並且下拉列表甚至沒有填充。

回答

0

你的主要問題是你需要設置你的指令的高優先級,以使它的編譯函數在ngModel的一個(也是ngIf's)之前執行。對於這一點,不要手動編譯,但執行的指令的編譯功能:

.directive('myDirective', function($compile) { 
    return { 
     priority: 10000, 
     terminal: true, 
     link: function(scope, element) { 
     element.attr('ng-options', 'item as item.label for item in items').removeAttr('my-directive'); 
     $compile(element)(scope); 
     } 
    } 
    }) 

您還需要記住的是,如果你使用的是創建新範圍(如ngIf,ngInclude等)的指令,你可能會得到當模型不會更新時出現意外行爲,因爲Angular會將值寫入子範圍模型。在您的演示中,我使用$parent來明確指出適當範圍,但最好使用controllerAs表示法來消除此類問題。

你也不想在指令鏈接函數中設置項目,但我想這只是爲了演示的目的,你應該將它移動到控制器。

演示:http://codepen.io/anon/pen/KVwQYr?editors=101

+0

我正忙着編制一個答案時,你打我吧。只有一個問題,爲什麼你需要'ng-if =「條件|| true」'指令來使它工作?請參閱第一個例子,其中存在'ng-if =「condition || true」'。然後在第二個例子中'ng-if =「條件|| true」'不存在,並且'select'選項沒有被填充。 1. https://jsfiddle.net/vg2wgamg/ 2. https://jsfiddle.net/2qzjkpqL/我總是可以問這個問題,讓你在那裏回答它? –

+0

@TjaartvanderWalt這真的很棘手的問題。我不清楚自己是什麼導致了這種行爲,但是它與ngIf創建的附加嵌套範圍有關。我找到的解決方案是添加'terminal:true'指令來防止進一步編譯(?)。我還發現有必要在鏈接函數中手動編譯元素。檢查更新的演示。 – dfsq

+0

好的。我測試過了,你以前的例子工作正常,因爲它在指令的編譯函數中。我不認爲你需要手動使用'$ compile'服務,就像你在更新後的代碼示例中那樣 –