AngularJS -如何在自定义指令中改变ngModel的值?

时间:2022-09-26 11:22:39

Lets take a look to my directive:

让我们看看我的指示:

angular.module('main').directive('datepicker', [
function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, ngModel) {
            ngModel.$modelValue = 'abc'; // this does not work
            // how do I change the value of the model?

So, how do I change the value of the ng-model?

那么,如何改变ng模型的值呢?

5 个解决方案

#1


41  

There are different ways of doing it:

有不同的方法:

  1. $setViewValue() updates the view and the model. Most cases it is enough.
  2. $setViewValue()更新视图和模型。大多数情况下这就足够了。
  3. If you want to disconnect view from the model (e.g. model is a number but view is a string with thousands separators) then you could access directly to $viewValue and $modelValue
  4. 如果您想从模型中断开视图(例如,模型是一个数字,但是视图是一个有数千个分隔符的字符串),那么您可以直接访问$viewValue和$modelValue
  5. If you also want to overwrite the content of ng-model (e.g. the directive changes the number of decimals, updating also the model), inject ngModel: '=' on the scope and set scope.ngModel
  6. 如果您还想覆盖ng-model的内容(例如,指令改变小数的数量,同时更新模型),那么在作用域和set作用域.ngModel上注入ngModel: '='

e.g.

如。

  return {
     restrict: 'A',
     require: 'ngModel',
     scope: {
         ngModel: '='
     },
     link: function (scope, element, attrs, ngModelCtrl) {

        function updateView(value) {
            ngModelCtrl.$viewValue = value;
            ngModelCtrl.$render(); 
        }

        function updateModel(value) {
            ngModelCtrl.$modelValue = value;
            scope.ngModel = value; // overwrites ngModel value
        }
 ...

LINKS:

链接:

  • 1st option is discussed here
  • 这里讨论第一个选项
  • NgModelController official docs
  • NgModelController官方文档

#2


26  

To work with complex binding expressions you should use the $parse service and the assign method.

要使用复杂的绑定表达式,您应该使用$parse服务和assign方法。

For more information watch this video from ng-conf - it's all about the cool things you can do with the ng-model directive: https://www.youtube.com/watch?v=jVzymluqmg4

要了解更多信息,请观看这段来自ng-conf的视频——它是关于ng-model指令可以做的很酷的事情:https://www.youtube.com/watch?v=jVzymluqmg4

app.directive('datepicker', ['$parse',
    function($parse) {
        return {
            require: '?ngModel',
            link: function(scope, element, attributes, controller) {
                // $parse works out how to get the value.
                // This returns a function that returns the result of your ng-model expression.
                var modelGetter = $parse(attributes['ngModel']);
                console.log(modelGetter(scope));

                // This returns a function that lets us set the value of the ng-model binding expression:
                var modelSetter = modelGetter.assign;

                // This is how you can use it to set the value 'bar' on the given scope.
                modelSetter(scope, 'bar');

                console.log(modelGetter(scope));
            }
        };
    }
]);

#3


4  

What you tried is actually working: see this Plunker

你所尝试的实际上是工作:看看这个活塞!

You don't "see" it in the input because changing the model this way doesn't call controller.$render() to set the new controller.$viewValue.

您不会在输入中“看到”它,因为以这种方式更改模型不会调用controller.$render()来设置新的控制器。

But why don't you simply change the $scope value (unless you don't know it, but it would be weird):

但是,为什么不简单地更改$scope值(除非您不知道它,但是它会很奇怪):

angular.module('main').directive('datepicker', [function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, controller) {
          var model = attributes['ngModel'];
          scope[model] = 'bar';
        }
    };
}]);

And in your html:

在你的html:

<input ng-model="yourVariable" datepicker>

EDIT: (dynamic solution)

编辑(动态解决方案):

angular.module('main').directive('datepicker', [function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, controller) {
          // get the value of the `ng-model` attribute
          var model = attributes['ngModel'];

          // update the scope if model is defined
          if (model) {
            scope[model] = 'bar';
          }
        }
    };
}]);

#4


1  

This works for a DatePicker on my site

这适用于我的站点上的DatePicker

link: function(scope, elem, attrs, ngModel) {
         scope.$apply(function(){
             ngModel.$viewValue = value;
         }
} 

#5


1  

Here's the best explanation I've encountered. This helped me big time, and brings together details from a number of the other answers here.

这是我遇到的最好的解释。这给了我很大的帮助,并把这里的许多其他答案的细节汇集在一起。

TIP: Be careful to read the whole article rather than skim it, or else you're likely to miss some key bits!

提示:要小心阅读整篇文章而不是浏览它,否则你可能会漏掉一些关键的部分!

https://www.nadeau.tv/using-ngmodelcontroller-with-custom-directives/

https://www.nadeau.tv/using-ngmodelcontroller-with-custom-directives/

#1


41  

There are different ways of doing it:

有不同的方法:

  1. $setViewValue() updates the view and the model. Most cases it is enough.
  2. $setViewValue()更新视图和模型。大多数情况下这就足够了。
  3. If you want to disconnect view from the model (e.g. model is a number but view is a string with thousands separators) then you could access directly to $viewValue and $modelValue
  4. 如果您想从模型中断开视图(例如,模型是一个数字,但是视图是一个有数千个分隔符的字符串),那么您可以直接访问$viewValue和$modelValue
  5. If you also want to overwrite the content of ng-model (e.g. the directive changes the number of decimals, updating also the model), inject ngModel: '=' on the scope and set scope.ngModel
  6. 如果您还想覆盖ng-model的内容(例如,指令改变小数的数量,同时更新模型),那么在作用域和set作用域.ngModel上注入ngModel: '='

e.g.

如。

  return {
     restrict: 'A',
     require: 'ngModel',
     scope: {
         ngModel: '='
     },
     link: function (scope, element, attrs, ngModelCtrl) {

        function updateView(value) {
            ngModelCtrl.$viewValue = value;
            ngModelCtrl.$render(); 
        }

        function updateModel(value) {
            ngModelCtrl.$modelValue = value;
            scope.ngModel = value; // overwrites ngModel value
        }
 ...

LINKS:

链接:

  • 1st option is discussed here
  • 这里讨论第一个选项
  • NgModelController official docs
  • NgModelController官方文档

#2


26  

To work with complex binding expressions you should use the $parse service and the assign method.

要使用复杂的绑定表达式,您应该使用$parse服务和assign方法。

For more information watch this video from ng-conf - it's all about the cool things you can do with the ng-model directive: https://www.youtube.com/watch?v=jVzymluqmg4

要了解更多信息,请观看这段来自ng-conf的视频——它是关于ng-model指令可以做的很酷的事情:https://www.youtube.com/watch?v=jVzymluqmg4

app.directive('datepicker', ['$parse',
    function($parse) {
        return {
            require: '?ngModel',
            link: function(scope, element, attributes, controller) {
                // $parse works out how to get the value.
                // This returns a function that returns the result of your ng-model expression.
                var modelGetter = $parse(attributes['ngModel']);
                console.log(modelGetter(scope));

                // This returns a function that lets us set the value of the ng-model binding expression:
                var modelSetter = modelGetter.assign;

                // This is how you can use it to set the value 'bar' on the given scope.
                modelSetter(scope, 'bar');

                console.log(modelGetter(scope));
            }
        };
    }
]);

#3


4  

What you tried is actually working: see this Plunker

你所尝试的实际上是工作:看看这个活塞!

You don't "see" it in the input because changing the model this way doesn't call controller.$render() to set the new controller.$viewValue.

您不会在输入中“看到”它,因为以这种方式更改模型不会调用controller.$render()来设置新的控制器。

But why don't you simply change the $scope value (unless you don't know it, but it would be weird):

但是,为什么不简单地更改$scope值(除非您不知道它,但是它会很奇怪):

angular.module('main').directive('datepicker', [function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, controller) {
          var model = attributes['ngModel'];
          scope[model] = 'bar';
        }
    };
}]);

And in your html:

在你的html:

<input ng-model="yourVariable" datepicker>

EDIT: (dynamic solution)

编辑(动态解决方案):

angular.module('main').directive('datepicker', [function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, controller) {
          // get the value of the `ng-model` attribute
          var model = attributes['ngModel'];

          // update the scope if model is defined
          if (model) {
            scope[model] = 'bar';
          }
        }
    };
}]);

#4


1  

This works for a DatePicker on my site

这适用于我的站点上的DatePicker

link: function(scope, elem, attrs, ngModel) {
         scope.$apply(function(){
             ngModel.$viewValue = value;
         }
} 

#5


1  

Here's the best explanation I've encountered. This helped me big time, and brings together details from a number of the other answers here.

这是我遇到的最好的解释。这给了我很大的帮助,并把这里的许多其他答案的细节汇集在一起。

TIP: Be careful to read the whole article rather than skim it, or else you're likely to miss some key bits!

提示:要小心阅读整篇文章而不是浏览它,否则你可能会漏掉一些关键的部分!

https://www.nadeau.tv/using-ngmodelcontroller-with-custom-directives/

https://www.nadeau.tv/using-ngmodelcontroller-with-custom-directives/