Используйте $formatter для значения ngModel, типизированного объектом, с работающим angular 1.2, но не с версией 1.3.

Этот код работал с angular-1.2.26, но не с angular-1.3.0.rc5 (или любыми версиями 1.3.x, которые я пробовал).

Я нашел эту проблему https://github.com/angular/angular.js/issues/9218 на github angular, но я не знаком с интерфейсом github и не могу понять, подтверждена ли ошибка или ожидается ли такое поведение, исправлена ​​она или нет; и если да, то какую версию брать.

JSFiddles:

Для каждого я ожидаю, что при загрузке страницы будет введена «моя метка». Для первого работает, для второго нет.

И посмотрите в консоли, какое значение передается форматтеру.

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;
            })
        }
    }
})

person M'sieur Toph'    schedule 25.10.2014    source источник


Ответы (1)


В 1.3 вы должны делать это так (что также будет работать в 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;
            })
        }
    }
})

Потому что, если вы unshift свой $formatter в 1.3, то вы получите строковое значение модели, если вы хотите иметь доступ к нестроковому значению модели, вам придется поставить $formatter в конце (push).

Я знаю, что это противоречит этому комментарию Игоря Минара.

Критическое изменение заключается в том, что значение viewValue, переданное в средства форматирования, будет версией toString отформатированного значения модели. Поэтому, если какие-либо пользовательские средства форматирования выполняются после средства форматирования по умолчанию, они увидят строковую версию значения. Если какое-либо средство форматирования нуждается в доступе к значению до того, как оно было преобразовано в строку, оно должно быть зарегистрировано через $formatters.unshift(customFormatter).

Но после этого комментария все изменилось .

Пример

person Josep    schedule 25.10.2014
comment
так что, если я понимаю (и rtfm), используя 1.3, я должен push форматтеры и unshift парсеры. Я думал, что пытался, но, может быть, не с версией r5 ... В любом случае, большое спасибо. - person M'sieur Toph'; 25.10.2014
comment
Ура, чтобы найти обходной путь, но это так нелогично. Как, черт возьми, первый форматировщик может получить строковый объект, а затем последний форматировщик получить фактический объект?! Разве, они выполняются в обратном порядке? - person Daniel Birowsky Popeski; 18.01.2015
comment
Да, документы теперь говорят: "Функции вызываются в обратном порядке массива, каждый из которых передает значение следующему». - person aarosil; 15.02.2015