Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a $formatter on a object typed ngModel value with angular 1.2 worked, but not with version 1.3

This code worked with angular-1.2.26, but not with angular-1.3.0.rc5 (or any 1.3.x versions I tried).

I found this issue https://github.com/angular/angular.js/issues/9218 on angular's github, but I am not familiar with github interface and I cannot figure out if the bug is confirmed or if the behavior is expected, if it has been fixed or not; and if yes, what version should I take.

JSFiddles :

  • with angular v1.2.26, ngModel as object
  • with angular v1.3.0.rc5, ngModel as object

For each, I expect to have 'my label' in the input when loading the page. It works for the first one, but not for the second.

And look at the console to see what value is passed to the formatter.

HTML :

<div ng-controller="ctrl as c">
    <input my-dir ng-model="c.foobar" />
    <pre>{{c.foobar | json}}</pre>
</div>

JS :

var app = angular.module('app', []);

app.controller('ctrl', function(){
    this.foobar = {
        value : 'my value',
        label : 'my label'
    }
})


.directive('myDir', function(){
    return {
        restrict :'A',
        require:'ngModel',
        link : function(scope, elt, attrs, modelCtrl){

            // conversion "view -> model"
            modelCtrl.$parsers.unshift( function(value){
                console.log('Value:', value);
                return {label:value, value:value};
            })

            // conversion "model -> view"
            modelCtrl.$formatters.unshift(function formatter(modelValue){
                console.log('modelValue:', modelValue);
                return modelValue.label;
            })
        }
    }
})
like image 935
M'sieur Toph' Avatar asked Dec 19 '22 10:12

M'sieur Toph'


1 Answers

In 1.3 you should be doing it like this (which will also work in 1.2):

.directive('myDir', function(){
    return {
        restrict :'A',
        require:'ngModel',
        link : function(scope, elt, attrs, modelCtrl){
            
            // conversion "view -> model"
            modelCtrl.$parsers.push( function(value){
                console.log('Value:', value);
                return {label:value, value:value};
            })
            
            // conversion "model -> view"
            modelCtrl.$formatters.push(function formatter(modelValue){
                console.log('modelValue:', modelValue);
                return modelValue.label;
            })
        }
    }
})

Because if you unshift your $formatter in 1.3, then you will get the stringified value of the model, if you want to have access to the non stringified value of the model, you will have to put your $formatter at the end (push).

I know that this contradicts this comment of Igor Minar.

The breaking change is that the viewValue passed into formatters will be a toString version of the formatted modelValue. So if any custom formatters execute after the default formatter, they'll see the string version of the value. If any formatter needs access to the value before it was stringified, the formatter should be registered via $formatters.unshift(customFormatter).

But things changed after that comment.

Example

like image 89
Josep Avatar answered May 12 '23 11:05

Josep