1

While trying to access $modelValue and $viewValue from inside custom directives, I am getting null.

var demo = angular.module('demo', []);
demo.directive('dogInfo', function($parse) {
    return {
        restrict: 'E',
        require: 'ngModel',
        template: "<div> Dog's name: {{dogname}}<br>View Name: {{viewValue}}<br>Model Value: {{modelValue}}<br> Tag name: {{tagName}}</div>",
        link: function (scope, element, attrs, controller) {
            scope.viewValue = controller.$viewValue;
            scope.modelValue = controller.$modelValue;
            scope.tagName = controller.$name;
        }
    }});

function MyCtrl ($scope) {
    $scope.dogname = 'Hero';  // now    
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<div ng-app='demo'>
    <p ng-controller='MyCtrl'>
       <dog-info ng-model="dogname" name="Doggggyyy"/>.
    </p>
</div>

I am getting this output :

Dog's name: Hero
View Name: null
Model Value: null
Tag name: Doggggyyy

Here's the fiddle : http://jsfiddle.net/cxdun3y8/3/

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Daud
  • 7,429
  • 18
  • 68
  • 115
  • Similar question https://stackoverflow.com/questions/18458383/angularjs-read-initial-value-of-ngmodel-viewvalue-from-different-directive – sad comrade Mar 29 '18 at 10:25

2 Answers2

1

Try this approach:

demo.directive('dogInfo', function($parse) {
    return {
        restrict: 'E',
        require: 'ngModel',
        template: "<div> Dog's name: {{dogname}}<br>View Name: {{model.$viewValue}}<br>Model Value: {{modelValue}}<br> Tag name: {{tagName}}</div>",
        link: function (scope, element, attrs, controller) {
            scope.model = controller;
            scope.viewValue = controller.$viewValue;
            scope.modelValue = controller.$modelValue;
            scope.tagName = controller.$name;
        }
    }});

Pay attention to how I pass data to the view

Drag13
  • 5,859
  • 1
  • 18
  • 42
  • I don't get it.. you only created an alias for the controller and directly accessed the viewValue property in the template. Why shouldn't my approach work ? – Daud Jun 14 '16 at 09:44
  • Because ina first case you got the link to the direct value which is empty (for now) and will change only then. In a second case you get object, and value will be reevauated each digest. And always will be actual – Drag13 Jun 14 '16 at 09:46
  • ok.. Can I get the viewValue in the link function itself ? I need it to set it in scope so that I can access it in the template.. – Daud Jun 14 '16 at 09:58
  • What do you mean? Just $scope.value – Drag13 Jun 14 '16 at 10:39
  • I want to retrieve 'Hero' (value of 'dogname') inside the link function. – Daud Jun 14 '16 at 10:52
  • 1
    I see. You can achive this with several ways. Most natural, is to always ask ngModelController. like this: function callTheDog() {return ngModelCtrl.$viewValue + 'was called'; } But also you can push yout listner to the ngModelCtrl.$viewChangeListeners and when value will be change, you will be notifie, so you can do smth with your value. – Drag13 Jun 14 '16 at 11:10
0

According to answers here there are three working solutions

1) Using $timeout to wait until first digest end

$timeout(function() {
  initialViewValue = controller.$viewValue;
}, 0)

2) Using scope.watch

const off = scope.$watch(attrs.ngModel, () => {
  initialViewValue = controller.$viewValue;
  off();
});

3) Using $parse to get value immediately

const getter = $parse(attrs.ngModel);
let initialViewValue = getter(scope);

Also viewValue available as argument inside formatter callback

controller.$formatters.push(function(value) {
   viewValue = value
});

You'll probably want to remove callback if you only want to get initial value

sad comrade
  • 1,341
  • 19
  • 21