8

I am using AngularJS and I created a directive that requires 'ngModel':

'use strict';
angular.module('spot.im.embed').directive('sayBox', ['$sce', '$timeout', '$parse',
    function($sce, $timeout, $parse) {
        return {
            restrict: 'EA',
            require: 'ngModel',
            scope: {
            },
            link: function(scope, iElement, iAttrs, ngModel) {
                ngModel.$viewValue = 'adasd';
            }
        }
    }
]);

For reasons I don't know, the ng-model changes doesn't impact the view. Why is that? Is this the right way to change the ngModel value from a directive?

A J A Y
  • 585
  • 1
  • 7
  • 22
Naor
  • 23,465
  • 48
  • 152
  • 268

2 Answers2

20

$viewValue is property, $setViewValue is method that you are probably looking for

link: function (scope, iElement, iAttrs, ngModel) {
    ngModel.$setViewValue('adasd');
    ngModel.$render(); // depends – if you want update input value or only model value in the scope
}

$setViewValue(value, trigger);

This method should be called when an input directive want to change the view value; typically, this is done from within a DOM event handler.

documentation: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

Krzysztof Safjanowski
  • 7,292
  • 3
  • 35
  • 47
  • Should I call $render() myself? Why ngModel doesn't call to $render? – Naor Aug 10 '14 at 16:16
  • Yes, you should call `$render()`, try to run code http://jsfiddle.net/krzysztof_safjanowski/e00jdrsd/ . It is hard for me to write any suggestions without more context. What you are trying to resolve? – Krzysztof Safjanowski Aug 10 '14 at 18:02
4

It does not impact view, because $viewValue is updated on next digest cycle before it is displayed.

If you need to change view value not touching model value - you can do this using $formatters from NgModelController, and $parsers to update model value from view value (ngModel controller documentation).

link: function(scope, iElement, iAttrs, ngModel) {
  ngModel.$formatters.push(function(value){
    return 'adasd';
  });
}

http://plnkr.co/edit/gZslSeVa2Frq0edEbuWK?p=preview


UPD:

If you need to update model value directly (not just format value for displaying or parse user input), you can use $setViewValue (as it was mentioned in Krzysztof Safjanowski answer).

Other way to modify model value is to use data binding for isolated scope:

scope: {
    ngModel:'='
},
link: function(scope, iElement, iAttrs, ngModel) {
  scope.ngModel= 'adasd';
}

http://plnkr.co/edit/l9kEU03OwI03uVUc6AQ0?p=preview

If you are not using isolated scope it also posible to update model value, using $parse service:

 link: function(scope, iElement, iAttrs, ngModel) {
   $parse(iAttrs.ngModel).assign(scope, 'adasd');
 }

http://plnkr.co/edit/BDsaBxqgs9kJjnj8TsSz?p=preview

Bogdan Savluk
  • 6,274
  • 1
  • 30
  • 36