控制器有什么意义。$ viewValue / controller。$ modelValue?

时间:2015-11-04 19:48:03

标签: javascript angularjs angularjs-directive angular-ngmodel

我不清楚scope.ngModelcontroller.$viewValue / controller.$modelValue / controller.$setViewValue()之间的关系是什么,具体而言,后三者的关系是什么。例如,请参阅this 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.ngModelcontroller.$viewValue之间没有关系。似乎有任何我想做的事情,我只会使用scope.ngModel,并观察这些值。使用controller.$viewValuecontroller.$modelValue或使其与scope.ngModel保持同步有什么意义?

2 个答案:

答案 0 :(得分:0)

scope: { ngModel: '=' },为指令创建了一个独立的范围,这意味着指令中对foo的更改将不再反映在MyCtrl的父范围内。

此外,$setViewValue()所做的更改在调用controller.$render()之前不会反映在DOM中,这会告诉Angular在下一个摘要周期中更新DOM。

但是要回答这个问题,NgModelController及其方法实际上只有在你需要创建一些特殊的自定义数据绑定指令时才是必需的。对于正常的数据输入和验证,您不应该使用它。来自the documentation(强调我的):

  

[NgModelController]包含用于数据绑定,验证,CSS更新以及值格式化和解析的服务。它故意不包含任何处理DOM呈现或侦听DOM事件的逻辑。这种与DOM相关的逻辑应该由其他指令提供,这些指令利用NgModelController对控制元素进行数据绑定。 Angular为大多数输入元素提供了这个DOM逻辑

答案 1 :(得分:0)

这里的困惑来自于将指令粘贴到现有指令上,即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",即使指令的视图值属于不同类型。