Пользовательская директива не принимает инициализацию модели - PullRequest
0 голосов
/ 11 июня 2018

Я написал пользовательскую директиву AngularJS, которая реализует переключатель переключения на основе Bootstrap Toggle .Я добавил поддержку angular-translate , но это выходит за рамки моей реальной задачи.Кроме того, я хотел использовать angular-cookies для сохранения и восстановления текущего состояния определенного флажка.

Однако моя директива не принимает начальное значениеМодель данных правильно.

Это моя директива:

app.directive('toggleCheckbox', ['$rootScope', '$translate', '$timeout', function($rootScope, $translate, $timeout) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attributes, ngModelController) {

      // Change model, when checkbox is toggled
      element.on('change.toggle', function(event) {
        var checked = element.prop('checked');
        console.log('change.toggle was called: ' + checked + ' vs. ' + ngModelController.$viewValue);
        if (checked != ngModelController.$viewValue) {
          scope.$apply(function changeViewModel() {
            ngModelController.$setViewValue(checked);
            console.log('change.toggle:', checked);
          });
        }
      });

      // Render element
      ngModelController.$render = function() {
        element.bootstrapToggle(ngModelController.$viewValue ? 'on' : 'off')
      };

      // Translate checkbox labels
      var updateLabels = function() {
        var offLabel = (attributes['off'] ? $translate.instant(attributes['off']) : 'Off');
        var onLabel  = (attributes['on']  ? $translate.instant(attributes['on'])  : 'On');

        angular.element(document).find('label.btn.toggle-off').html(offLabel);
        angular.element(document).find('label.btn.toggle-on').html(onLabel);
      };

      // Update labels, when language is changed at runtime
      $rootScope.$on('$translateChangeSuccess', function() {
        updateLabels();
      });

      // Initialize labels for the first time
      $timeout(function() {
        updateLabels();
      });

      // Clean up properly
      scope.$on('$destroy', function() {
        element.off('change.toggle');
        element.bootstrapToggle('destroy');
      });

      // Initialize element based on model
      var initialValue = scope.$eval(attributes.ngModel);
      console.log('initialValue:', initialValue);
      element.prop('checked', initialValue);
    }
  };
}]);

Вот как я инициализирую модель данных из cookie:

mainController.controller('MainCtrl', ['$scope', '$cookies', 'Main', function($scope, $cookies, Main) {

  this.$onInit = function() {
    $scope.settings.foobar = $cookies.get('foobar');
    console.log('$onInit(): ', $scope.settings.foobar);
  };

  // ...

}]);

И этокак я в конечном итоге использую свою директиву:

<div id="foobar-switcher" ng-if="isAdmin()">
  <label for="foobar_toggle"><span translate="foobar"></span>:</label>
  <input id="foobar_toggle" type="checkbox"
    ng-model="settings.foobar" ng-change="setFoobarCookie(settings.foobar)" toggle-checkbox
    data-off="foo_label" data-offstyle="success"
    data-on="bar_label" data-onstyle="danger" />
</div>

В конечном итоге я получаю отладочный вывод:

controllers.js: 33 $ onInit (): true

directives.js: 76 initialValue: true

directives.js: 37 был вызван change.toggle: false vs. false

Таким образом, в случае, если значение true хранится вcookie, модель правильно инициализируется в глобальной области видимости, и даже директива использует правильное значение для инициализации element.Обработчик события change.toggle также запускается, но там значение элемента теперь равно false.

Почему это так и как я могу решить эту проблему?

1 Ответ

0 голосов
/ 15 июня 2018

Оказалось, что $cookies.get('foobar') возвращает строку, и флажок не может обработать ng-model этого типа.Вместо этого значение cookie должно быть оценено таким образом, чтобы в модели данных можно было установить логическое значение:

var cookie = $cookies.get('foobar');
$scope.settings.foobar = (cookie === 'true');

. Затем флажок корректно инициализируется при загрузке страницы.

...