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). Я попытался внести изменения DOM в этап compile директивы, но $scope.items неизвестен, а выпадающее меню даже не заселено.

ответ

0

Ваша основная проблема заключается в том, что вам нужно установить действительно высокий приоритет вашей директивы, чтобы выполнить ее функцию компиляции перед ngModel (и ngIf тоже). Для этого не нужно компилировать вручную, но реализовать функцию компиляции директивы:

.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 =» условие || true ". Затем во втором примере условие «ng-if =» || true "' отсутствует, а опции 'select' не заполняются. 1. https://jsfiddle.net/vg2wgamg/ 2. https://jsfiddle.net/2qzjkpqL/ Я всегда могу задать вопрос и позволить вам ответить на него там? –

+0

@TjaartvanderWalt Это действительно сложная проблема. Я не совсем понимаю, что вызывает это поведение, однако он связан с дополнительной вложенной областью, созданной ngIf. Решение, которое я нашел, заключается в том, чтобы добавить команду 'terminal: true', чтобы предотвратить дальнейшую компиляцию (?). Я также обнаружил, что необходимо вручную скомпилировать элемент в функции ссылок. Проверьте обновленную демоверсию. – dfsq

+0

Хорошо. Я тестировал, и ваш предыдущий пример работал нормально, как и в функции компиляции директивы. Я не думаю, что вам нужно вручную использовать службу '$ compile', как это было в вашем обновленном примере кода –

 Смежные вопросы

  • Нет связанных вопросов^_^