В чем смысл контроллера. $ ViewValue / controller. $ ModelValue?

0

Я не знаю, какова связь между scope.ngModel и controller.$viewValue/controller.$modelValue/controller.$setViewValue() есть и, в частности, то, что точка последних трех. Например, см. Этот jsfiddle:

<input type="text" ng-model="foo" my-directive>

а также:

myApp.directive('myDirective', function($timeout) {
    return {
        require: 'ngModel', 
        restrict: 'A',
        scope: { ngModel: '=' },
        link: function (scope, element, attrs, controller) {
            function log() {
              console.log(scope.ngModel);
              console.log(controller.$viewValue);
              console.log(controller.$modelValue);
            }
            log();
            controller.$setViewValue("boorb");
            log();
            scope.$watch('ngModel', function (val) {
               console.log("val is now", val); 
            });

            $timeout(function () {
                log();
            }, 2000);

        }
    }
});

При наличии контроллера:

function MyCtrl($scope, $timeout) {
    $scope.foo = 'ahha';
    $timeout(function () { 
        $scope.foo = "good";
    }, 1000);
}

Выход:

(index):45 ahha
(index):46 NaN
(index):47 NaN
(index):45 ahha
(index):46 boorb
(index):47 boorb
(index):53 val is now ahha
(index):53 val is now good
(index):45 good
(index):46 boorb
(index):47 boorb

controller.$viewValue не начинался как значение переменной foo. Кроме того, controller.$setViewValue("boorb") не влиял на scope.ngModel вообще, и обновление не отразилось в HTML. Таким образом, кажется, что нет никакой связи между scope.ngModel и controller.$viewValue. Кажется, что с чем-то, что я хотел бы сделать, я бы просто использовал scope.ngModel и наблюдал эти значения. Какой смысл использовать controller.$viewValue и controller.$modelValue или поддерживать их в актуальном состоянии с помощью области scope.ngModel?

Теги:
angular-ngmodel
angularjs-directive

2 ответа

0
Лучший ответ

Путаница здесь происходит от ngInput директивы на существующую директиву, а именно на ngInput.

Вместо этого рассмотрите новую директиву:

<my-directive ng-model="ugh">Sup</my-directive>

С:

  $rootScope.ugh = 40;

А также:

.directive('myDirective', function () {
  return {
    require: "ngModel", 

    // element-only directive
    restrict: "E", 

    // template turns the directive into one input tag
    // 'inner' is on the scope of the *directive*
    template: "<input type='text' ng-model='inner'/>",       

    // the directive will have its own isolated scope
    scope: { }, 

    link: function (scope, element, attrs, ngModelCtrl) {
      // formatter goes from modelValue (i.e. $rootScope.ugh) to 
      // view value (in this case, the string of twice the model
      // value + '-'
      ngModelCtrl.$formatters.push(function (modelValue) {
        return ('' + (modelValue * 2)) + '-';
      });

      // render does what is necessary to display the view value
      // in this case, sets the scope.inner so that the inner
      // <input> can render it
      ngModelCtrl.$render = function () {
        scope.inner = ngModelCtrl.$viewValue;
      };

      // changes on the inner should trigger changes in the view value
      scope.$watch('inner', function (newValue) {
        ngModelCtrl.$setViewValue(newValue);
      });

      // when the view value changes, it gets parsed back into a model
      // value via the parsers, which then sets the $modelValue, which
      // then sets the underlying model ($rootScope.ugh)
      ngModelCtrl.$parsers.push(function (viewValue) {
        var sub = viewValue.substr(0, viewValue.length-1);
        return parseInt(sub)/2;
      });
    }
  };
})

Попробуйте это на Plunker.

Обратите внимание, что typeof ugh остается "number", хотя значение представления директивы имеет другой тип.

0

scope: { ngModel: '=' }, создает изолированную область действия для директивы, а это означает, что изменения в foo в директиве больше не будут отображаться в родительской области MyCtrl.

Кроме того, изменения, сделанные с помощью $setViewValue(), не будут отображаться в DOM до controller.$render() $setViewValue() controller.$render(), который сообщает Angular об обновлении DOM в следующем цикле дайджеста.

Но чтобы ответить на этот вопрос, NgModelController и его методы действительно необходимы только в том случае, если вам нужно создать некоторые специальные специальные настройки для привязки данных. Для нормального ввода и проверки данных вам никогда не придется использовать его. Из документации (акцент мой):

[NgModelController] содержит службы для привязки данных, проверки, обновления CSS и форматирования и разбора значений. Он целенаправленно не содержит никакой логики, которая связана с рендерингом DOM или прослушиванием событий DOM. Такая логика, связанная с DOM, должна предоставляться другими директивами, которые используют NgModelController для привязки данных к элементам управления. Угловой обеспечивает эту логику DOM для большинства входных элементов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню