AngularJS - how to change the value of ngModel in custom directive?

后端 未结 5 1049
再見小時候
再見小時候 2020-12-23 09:53

Lets take a look to my directive:

angular.module(\'main\').directive(\'datepicker\', [
function() {
    return {
        require: \'?ngModel\',
        link:         


        
相关标签:
5条回答
  • 2020-12-23 10:08

    This works for a DatePicker on my site

    link: function(scope, elem, attrs, ngModel) {
             scope.$apply(function(){
                 ngModel.$viewValue = value;
             }
    } 
    
    0 讨论(0)
  • 2020-12-23 10:08

    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 are likely to miss some key bits!

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

    0 讨论(0)
  • 2020-12-23 10:10

    There are different ways of doing it:

    1. $setViewValue() updates the view and the model. Most cases it is enough.
    2. 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
    3. 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

    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
    0 讨论(0)
  • 2020-12-23 10:16

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

    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

    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));
                }
            };
        }
    ]);
    
    0 讨论(0)
  • 2020-12-23 10:18

    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.

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

    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:

    <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';
              }
            }
        };
    }]);
    
    0 讨论(0)
提交回复
热议问题