Подтвердить что ты не робот

Bootstrap "buttons-radio" переключается с AngularJS

Я сделал небольшой модуль angular для интеграции с бутстрапом "buttons-group" (плюс немного javascript, чтобы заставить их работать как переключатели. Я сделал это на этом модуле, чтобы сделать то же самое для флажков: http://jsfiddle.net/evaneus/z9rge/

Мой код находится в http://jsfiddle.net/askbjoernhansen/YjMMD/

Мои вопросы:

1) Правильно ли это подходит?

2) Будет ли наблюдаться модель три раза или $scope. $watch() выяснить, что это одна и та же модель, и просто сделать это один раз? Кажется, что так.

3) Правильно ли это гадать с DOM в функции $watch, как я? Он чувствует себя "грязным", но я предполагаю, что то, о чем я прошу, когда добавляю angular к чему-то, что не согласуется с angularjs. Или?

4) Есть ли способ поместить атрибут ng-model в группу btn вместо каждой кнопки? Это сделает его намного более чистым.

Вы можете увидеть это в моем jsfiddle выше, или код здесь, сначала html:

 <!-- to test the two-way model -->
  <input name="test" type="radio" ng-model="myModel['A']" value="left"> Left<br>
  <input name="test" type="radio" ng-model="myModel['A']" value="middle"> Middle<br>
  <input name="test" type="radio" ng-model="myModel['A']" value="right"> Right<br>


myModel A {{myModel['A']}}<br/>

<div class="btn-group" data-toggle="buttons-radio">
  <button type="button" buttons-radio=""
    ng-model="myModel['A']" value="left"   class="btn">Left</button>
  <button type="button" buttons-radio=""
    ng-model="myModel['A']" value="middle" class="btn">Middle</button>
  <button type="button" buttons-radio=""
    ng-model="myModel['A']" value="right"  class="btn">Right</button>
</div>

И javascript:

angular.module('buttonsRadio', []).directive('buttonsRadio', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function($scope, element, attr, ctrl) {
            element.bind('click', function() {
                $scope.$apply(function(scope) {
                    ctrl.$setViewValue(attr.value);
                });
            });

            // This should just be added once, but is added for each radio input now?
            $scope.$watch(attr.ngModel, function(newValue, oldValue) {
                element.parent(".btn-group").find('button').removeClass("active");
                element.parent(".btn-group")
                .find("button[value='" + newValue + "']").addClass('active');
            });
        }
    };
});​
4b9b3361

Ответ 1

Вы вызываете директиву три раза, один раз для каждой кнопки. AFAIK это означает, что функция связывания называется три раза, связывая события и наблюдая за изменениями. добавлено немного подробнее об этом ниже.

Прекрасно менять DOM при изменении моделей, но то, что вы делаете - изменение классов и значений - может выполняться автоматически с помощью angular с использованием двунаправленных привязок к данным и родных директив, таких как ng-class

Вы можете создать директиву, которая отображает кнопки с указанием списка параметров. Например, если у вас есть эта модель и эти параметры

$scope.myOptions = ["Left", "Middle", "Right"];
$scope.myModel = "Left"

Вы можете создать директиву buttons-radio, подобную этой

App.directive('buttonsRadio', function() {
    return {
        restrict: 'E',
        scope: { model: '=', options:'='},
        controller: function($scope){
            $scope.activate = function(option){
                $scope.model = option;
            };      
        },
        template: "<button type='button' class='btn' "+
                    "ng-class='{active: option == model}'"+
                    "ng-repeat='option in options' "+
                    "ng-click='activate(option)'>{{option}} "+
                  "</button>"
    };
});​

который можно вызвать из вашего HTML

<buttons-radio class="btn-group" data-toggle="buttons-radio" 
               model='myModel'    
               options='myOptions'>
</buttons-radio>

Замечания:

  • В шаблоне используется директива ng-repeat, которая проходит через все опции и компилирует соответствующие кнопки.
  • Директива имеет свой собственный контроллер и изолированную область с model и options для принятия двунаправленного связывания, поэтому angular делает свою магию, когда директива изменяет свои значения.
  • Если опция соответствует текущему значению модели, то кнопке присваивается класс active.
  • При нажатии кнопки вызывается метод activate (из контроллера директив) и изменяется значение модели.

Heres a JSFiddle http://jsfiddle.net/jaimem/A5rvg/4/


ИЗМЕНИТЬ

Я не был полностью уверен в этом, но да, у вашей модели будут три разные наблюдатели, по одному для каждого вызова директивы. Если вы используете Batarang, вы можете увидеть все просмотренные выражения на вкладке "Производительность" и панели "Угловые атрибуты". Batarang также предоставляет удобное свойство $scope, поэтому вы можете искать свои объекты для просмотра модели, запустив следующее с консоли

$scope.$$watchers.filter(function(w){return w.exp ==="myModel['A']"}); 

Ответ 2

это просто

<html>
    <div class="btn-group" data-toggle="buttons">
      <span class="btn btn-primary" ng-click="worktype=1" ng-class="worktype==1?'active':''">
        <input type="radio"   value="1">全职
      </span>
      <span class="btn btn-primary" ng-click="worktype=2" ng-class="worktype==2?'active':''">
        <input type="radio"   value="2">兼职
      </span>
    </div>
</html>