5

Я люблю Bootstrap-Select и я в настоящее время использовать его через помощью директивы, сделанного другим пользователем joaoneto/angular-bootstrap-select, и она работает как задумано, за исключением, когда я пытаюсь заполнить мой <select> элемент с $http или в мой случай a dataService обертка. Я, кажется, получаю некоторую проблему с синхронизацией, данные появляются после того, как selectpicker получил отображение/обновление, а затем у меня есть пустой список Bootstrap-Select. Хотя с Firebug я вижу список значений в скрытом теперь <select>. Если я затем зашел в консоль и вручную выполнил $('.selectpicker').selectpicker('refresh'), тогда он будет работать.
Я получил его временно, выполнив патч и добавив .selectpicker('refresh') внутри $timeout, но, как вы знаете, он не идеален, так как мы используем jQuery прямо в ngController ... ouch!

Так что я считаю, что в директиве, возможно, отсутствует наблюдатель или, по крайней мере, что-то, что может вызвать изменение или обновление ngModel.

Html код образца:Угловая Bootstrap-Выберите вопрос времени, чтобы обновить

<div class="col-sm-5"> 
    <select name="language" class="form-control show-tick" 
     ng-model="vm.profile.language" 
     selectpicker data-live-search="true" 
     ng-options="language.value as language.name for language in vm.languages"> 
    </select> 
    <!-- also tried with an ng-repeat, which has the same effect --> 
</div> 

затем внутри моего углового контроллера:

// get list of languages from DB 
dataService 
    .getLanguages() 
    .then(function(data) { 
     vm.languages = data; 

     // need a timeout patch to properly refresh the Bootstrap-Select selectpicker 
     // not so good to use this inside an ngController but it's the only working way I have found 
     $timeout(function() { 
      $('.selectpicker, select[selectpicker]').selectpicker('refresh'); 
     }, 1); 
    }); 

и вот директива сформулированное (joaoneto) на GitHub for Angular-Bootstrap-Select

function selectpickerDirective($parse, $timeout) { 
    return { 
    restrict: 'A', 
    priority: 1000, 
    link: function (scope, element, attrs) { 
     function refresh(newVal) { 
     scope.$applyAsync(function() { 
      if (attrs.ngOptions && /track by/.test(attrs.ngOptions)) element.val(newVal); 
      element.selectpicker('refresh'); 
     }); 
     } 

     attrs.$observe('spTheme', function (val) { 
     $timeout(function() { 
      element.data('selectpicker').$button.removeClass(function (i, c) { 
      return (c.match(/(^|\s)?btn-\S+/g) || []).join(' '); 
      }); 
      element.selectpicker('setStyle', val); 
     }); 
     }); 

     $timeout(function() { 
     element.selectpicker($parse(attrs.selectpicker)()); 
     element.selectpicker('refresh'); 
     }); 

     if (attrs.ngModel) { 
     scope.$watch(attrs.ngModel, refresh, true); 
     } 

     if (attrs.ngDisabled) { 
     scope.$watch(attrs.ngDisabled, refresh, true); 
     } 

     scope.$on('$destroy', function() { 
     $timeout(function() { 
      element.selectpicker('destroy'); 
     }); 
     }); 
    } 
    }; 
} 
+0

AngularJS версия? – tasseKATT

+0

Версия AngularJS 1.3.11 – ghiscoding

ответ

9

Одна из проблем, с угловой -bootstrap-select, заключается в том, что он смотрит только ngModel, а не на объект, который фактически заполняет параметры в sele кт. Например, если vm.profile.language по умолчанию установлено '', а vm.languages имеет опцию '', выбор не будет обновляться новыми параметрами, потому что ngModel остается неизменным. Я добавил атрибут selectModel для выбора и немного изменил код углового бутстрапа.

<div class="col-sm-5"> 
    <select name="language" class="form-control show-tick" 
     ng-model="vm.profile.language" 
     select-model="vm.languages" 
     selectpicker data-live-search="true" 
     ng-options="language.value as language.name for language in vm.languages"> 
    </select> 
</div> 

Затем в угловой самозагрузке-выборе кода, я добавил

if (attrs.selectModel) { 
    scope.$watch(attrs.selectModel, refresh, true); 
} 

Теперь, когда vm.languages обновляется, то выберите будет обновляться тоже. Лучшим методом, вероятно, было бы просто определить, какой объект следует отслеживать, используя ngOptions, но с помощью этого метода можно также использовать ngRepeat в рамках выбора.

Edit:

Альтернативой использованию selectModel автоматически обнаруживать объект смотреть от ngOptions.

if (attrs.ngOptions &&/in /.test(attrs.ngOptions)) { 
    scope.$watch(attrs.ngOptions.split(' in ')[1], refresh, true); 
} 

Edit 2:

Вместо того чтобы использовать функцию refresh, вы, вероятно, будет лучше просто звоню element.selectpicker('refresh'); снова, как вы только хотите, чтобы фактически обновить значение избранных, когда ngModel изменения. Я столкнулся с сценарием, в котором обновлялся список опций, и значение select изменилось, но модель не изменилась, и в результате она не соответствовала selectpicker. Это решить это для меня:

if (attrs.ngOptions &&/in /.test(attrs.ngOptions)) { 
    scope.$watch(attrs.ngOptions.split(' in ')[1], function() { 
     scope.$applyAsync(function() { 
      element.selectpicker('refresh'); 
     }); 
    }, true); 
} 
+0

Очень интересная концепция, это дало мне представление об использовании обновления без необходимости в атрибуте. Поскольку у нас уже есть имя объекта непосредственно внутри 'ngOptions', вы можете сделать это, только изменив сама директиву и добавив что-то вроде следующего:' if (attrs.ngOptions &&/in /.test(attrs.ngOptions) {scope. $ watch (attrs.ngOptions.split ('in') [1], refresh, true);} '... отредактируйте свой ответ с помощью этой опции или, лучше, и я приму ваш ответ ... большое спасибо :) – ghiscoding

+0

Это отличное решение для меня, спасибо! – WiseGuy

0

Я извиняюсь, но где в угловой самозагрузке-коде выборе вы добавили этот код? Я спрашиваю, потому что он говорит, что attrs не определен.

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