AngularJS и плагин jQuery UI
В общем, есть на странице селект, по которому фильтруется вывод основных данных. Он должен быть декорирован Selectmenu.
Я набросал простейшую директиву: function($scope, element, attrs, controller) { // Получаю опции из атрибута var options = $scope.$eval(attrs['selector']); angular.extend(options, { // Без этого модель привязанная к селекту не обновляется change: function(event, object) { element.trigger('change'); } }); // Применяю плагин $(element).selectmenu(options); } Тут всё хорошо, всё работает. Но т.к. приложение RESTfull (это мой первый опыт) данные для селекта должны подгружаться динамически. И в итоге получается, что когда данные пришли и оригинальный селект заполнился - Selectmenu уже применён и пустой. Причём получается от случая к случаю: обновляешь страницу, если данные пришли быстро - то и в декорированном селекте появились, если нет то он пустой (оригинальный, который скрыт в порядке). Я пробовал вызывать .selectmenu("refresh"); после загрузки данных: $scope.staffList = Staff.query({fOnlyAuthors: 1}, function(){ // console.log(jQuery(".selector", element).length) jQuery(".selector", element).selectmenu("refresh"); }); Но это эффекта не имеет, селект по прежнему остаётся пустым. Подскажите как правильно решить данный вопрос? Как-то организовать отложенное применение декорирующей директивы или обновление плагина? |
можно демку на plunker ?
|
делай по аналогии
/* ОБертка для jquery-chosen */ .directive('ngChosen', function() { return { replace: true, link: function(scope, element, attributes) { var params = scope.$eval(attributes.ngChosen) || {}; element.chosen(params); function handler() { element.trigger('chosen:updated'); } element.bind('$destroy', scope.$watch(attributes.ngModel, handler)); element.bind('$destroy', scope.$watch(attributes.ngDisabled, handler)); } }; }) |
Цитата:
Что самое интересное, получается, если не трогать селект до того момента как получены данные - список формируется. Специально для проверки ставил таймаут, что б подольше получать данные, и до трёх-четырёх секунд грузятся, но появляются. А если сразу после загрузки страницы по декорированному селекту кликнуть, то он так и остаётся пустым в дальнейшем. // UPD: // Извиняюсь, тупанул, не тот триггер вызывал. Да, действительно сработало! Но мне не совсем понятно. Мы биндим триггер обновляющий список на событие $destroy. Почему именно на него? Что-то посмотрел в документацию, и не понял. Не могли бы вы вкратце объяснить, что происходит в данной ситуации? |
Ан, нет, снова я поспешил. Всё равно через раз работает. Поясните, пожалуйста, что нужно сделать, возможно я смогу подпилить?
По всей вероятности не вызывается событие когда надо. Если модель меняется уже после загрузки данных, до да, всё происходит как нужно. Но после первоначальной загрузки страницы список пуст. |
$scope.staffList = Staff.query({fOnlyAuthors: 1}, function(){ jQuery(".selector", element).selectmenu("destroy").selectmenu(); }); Вот так работает, т.е. директиву можно убрать вообще. Но вероятно это не правильно. Вообще не понятно почему в этом месте срабатывают корректно любые методы плагина (destroy, disable, open) только не refresh. |
html
<select ng-model="app.model.property" ng-options="item.id as item.title for item in app.dictionaries.categories" ng-chosen=""></select> js /** * jQuery-chosen wrapper * @see [url]http://harvesthq.github.io/chosen/[/url] */ .directive('ngChosen', [ function() { return { link: function(scope, element, attributes) { var options = scope.$eval(attributes.ngChosen); var settings = angular.extend({}, options); element.chosen(settings); element.bind('$destroy', scope.$watch(attributes.ngModel, handler)); element.bind('$destroy', scope.$watch(attributes.ngDisabled, handler)); element.bind('$destroy', destructor); // ----------------------- function handler() { element.trigger('chosen:updated'); } function destructor() { element.chosen('destroy'); } } }; } ]) |
Мой окончательный вариант:
directive('selector', function() { return { restrict: 'A', replace: true, //require: '?ngModel', link: function($scope, element, attributes, controller) { var options = $scope.$eval(attributes['selector']) || {}; angular.extend(options, { change: function(event, object) { element.trigger('change'); } }); element.selectmenu(options); element.bind('$destroy', $scope.$watch(attributes.ngModel, handler)); element.bind('$destroy', $scope.$watch(attributes.ngDisabled, handler)); element.bind('refresh-me', refreshMe); function handler() { element.selectmenu("refresh"); } function refreshMe() { element .selectmenu("destroy") .selectmenu(options); } } }; }); <select class="selector" ng-model="selectedStaff" ng-options="(staff.surname + ' ' + staff.name) for staff in staffList" data-selector="{icons: {button: 'ui-icon-list'}}"> $scope.staffList = Staff.query({}, function(){ $(".selector", element).trigger('refresh-me'); } Не уверен, что в полной мере правильно с точки зрения Angular, но задачу решает. nerv_, спасибо за помощь и наводки. |
Часовой пояс GMT +3, время: 19:37. |