обновить значения элемента директивы с помощью templateUrl

html-шаблон:

у меня есть элемент в файле шаблона seats.tpl.html, например:

<select  id="guest_table">
    <option tables="emptySeats"
            ng-repeat="table in emptySeats" value="{{table.tableId}}">{{table.tableNumber}}</option>
</select>

контроллер

в контроллер я вызываю фабрику, чтобы получить значения из базы данных, на самом деле я загружаю результат в массив $scope.emptySeats, который в шаблоне с ng-repeat создает:

factP3_GetEmptyChairs.getEmptyChairs({'data': {'id': 58}})
                .then(function (result) {
                    **$scope.emptySeats = result.data;**
                    $log.info("Empty chairs list loaded.");
                },
                function (result) {
                    $('.loading').hide();
                    $log.error("Error: we could not get Empty seats list.");
                });

директива:

в моей директиве я использую параметр templateUrl для вызова файла шаблона, чтобы загрузить, опять же пока все хорошо, выбор загружается со значениями.

.directive('emptySeats',function(){
        return {
            restrict: 'AE',
            replace: true,
            scope:{tables :'='},
            templateUrl: function(){
                return 'assets/modules/part3/templates/emptySeats.tpl.html';
            },

            link:function(scope, element, attrs) {                                                                           
                //bind change on element
                element.bind('change', function() {
                    alert("table changed");
                });

            }
        }

Моя проблема в том, что всякий раз, когда я изменяю значения массива $scope.emptySeats, мне нужно автоматически обновлять значения, чего не происходит с моим текущим кодом.

что-то, что я упустил в директиве, я думаю, это компилируется, это наблюдается, это ngmodel, кто-нибудь может помочь?

ОБНОВЛЕНО: я вызываю функцию, чтобы получить новые данные из базы данных и загрузить их для выбора элемента

 $scope.onClickHall = function (hall) {
    var tmp = [];
    //call service to load empty Seats
    factP3_GetEmptyChairs.getEmptyChairs({'data': {'id': $scope.currentHall}})
        .then(function (result) {
            //$scope.emptySeats = result.data;

A: Если я использую $apply здесь, я получаю: Ошибка: действие $rootScope:inprog уже выполняется

        $scope.$apply(function () {
                $scope.emptySeats = result.data;;
            });
            tmp = result.data; //i use a temp array to pass it on timeout

            $log.info("Empty chairs list loaded.");
        },
        function (result) {
            $('.loading').hide();
            $log.error("Error: we could not get Empty seats list.");
        });

Б. если я использую функцию $timeout и пытаюсь изменить данные, ничего не происходит

    $timeout(function() {
        $scope.$apply(function () {
            $scope.emptySeats = tmp;
        });
    }, 10);
}

person Theo Itzaris    schedule 31.07.2015    source источник


Ответы (2)


It would be better to use template files to enhance the capabilities of bootstrap popovers, tooltips, etc. There are two types of templates can be used to serve for the purpose.

  • Inline templates - Template code will define in the same HTML file and it will call by an angular directive.
    Example:

    <script type="text/ng-template" id="myTemplate.html">
       <h1>Hi</h1>
    </script>
    

  • Содержимое шаблона может быть определено во внешнем файле и может быть вызвано как запрос ajax. В этом подходе вам может понадобиться использовать вызов ajax, аналогичный $http.get(templateURL)

  • Определение директивы должно быть определено, как показано ниже, чтобы правильно прикрепить шаблон. Обратите внимание, что использование $compile для правильной интеграции содержимого. Это гарантирует, что содержимое будет правильно интегрировано в содержимое вашей директивы.

    Найдите ниже пример.

    angular.module('myApp')
          .directive('myPopover', function () {
            var getTemplate = function () {
                var template = '';
                    template = $templateCache.get("myTemplate.html");
                }
                return template;
            };
    
        return {
          restrict: 'A',
          transclude: true,
          scope: {
            text: '@myPopover'
          },
          link: function(scope, element, attrs) {
                var popOverContent = getTemplate();
                popOverContent = $compile("<div>" + popOverContent+"</div>")(scope);
    
                var options = {
                    //title       : title,
                    content     : popOverContent,
                    placement   : "right",
                    html        : true,
                    date        : scope.date,
                    trigger     : "hover"
                };
                $(element).popover(options);
          }
        };
      });
    

    Это работающий плункер.

    person Aviro    schedule 31.07.2015

    Поскольку ваш $http вызов является асинхронным, вам нужно вызвать $scope.$apply для запуска цикла $digest для повторного рендеринга представления директивы:

    $scope.$apply(function () {
       $scope.emptySeats = result.data;
    });
    

    $apply() используется для выполнения выражения в angular из-за пределов фреймворка angular. (Например, из событий браузера DOM, setTimeout, XHR или сторонних библиотек).

    person Joy    schedule 31.07.2015
    comment
    привет, я попробовал $scope.$apply и обновил свой вопрос - person Theo Itzaris; 31.07.2015