javascript - How to implement ng-model binding on this gettersetter scenario? - Stack Overflow

I have an object exposing 2 properties (say foo and bar) via getterssetters in the form of method([val

I have an object exposing 2 properties (say foo and bar) via getters/setters in the form of method([value]), so you can get their value by calling method() and you can set their value by calling method(value).

Also, this object keeps foo and bar synchronized, in the way it makes bar always to be 1 greater than foo). This means whenever you set the value of foo, it internally updates the value of bar, and viceversa.

This is the sample implementation:

function obj() {
    var foo = 1;
    var bar = 2;

    return {
        foo: function (value) {
            if (value) {
                foo = value;
                bar = foo + 1;
            }
            return foo;
        },
        bar: function (value) {
            if (value) {
                bar = value;
                foo = bar - 1;
            }
            return bar;
        }
    }    
}

Now I have two input elements, one for each of these properties.

// in my controller
$scope.myobj = obj();

<!-- in the HTML -->
<input my-directive ng-model="myobj.foo">
<input my-directive ng-model="myobj.bar">

Please remember that foo and bar are functions, so I write a $formatter to get the value by calling the getter; and a $parser to set the value by calling the setter, like this:

.directive('myDirective', function () {
    return {
        require: 'ngModel',
        link: function ($scope, $element, $attrs, ngModel) {
            ngModel.$formatters.push(function (modelValue) {
               return modelValue(); 
            });

            ngModel.$parsers.push(function (viewValue) {
               ngModel.$modelValue(viewValue);
               return ngModel.$modelValue;
            });
        }
    };
});

You can check the example in jsFiddle or Plunker.

As you can see, the formatter/parser thing works just fine, but the problem is that the <input> value of the property that is internally modified (say bar if you changed foo) is not updated.

I can't even grasp why in earth is not working. As you can see in the example, below each input I'm interpolating the same value which seems perfectly updated upon any change. Why ng-model isn't updating my <input> value?

I have an object exposing 2 properties (say foo and bar) via getters/setters in the form of method([value]), so you can get their value by calling method() and you can set their value by calling method(value).

Also, this object keeps foo and bar synchronized, in the way it makes bar always to be 1 greater than foo). This means whenever you set the value of foo, it internally updates the value of bar, and viceversa.

This is the sample implementation:

function obj() {
    var foo = 1;
    var bar = 2;

    return {
        foo: function (value) {
            if (value) {
                foo = value;
                bar = foo + 1;
            }
            return foo;
        },
        bar: function (value) {
            if (value) {
                bar = value;
                foo = bar - 1;
            }
            return bar;
        }
    }    
}

Now I have two input elements, one for each of these properties.

// in my controller
$scope.myobj = obj();

<!-- in the HTML -->
<input my-directive ng-model="myobj.foo">
<input my-directive ng-model="myobj.bar">

Please remember that foo and bar are functions, so I write a $formatter to get the value by calling the getter; and a $parser to set the value by calling the setter, like this:

.directive('myDirective', function () {
    return {
        require: 'ngModel',
        link: function ($scope, $element, $attrs, ngModel) {
            ngModel.$formatters.push(function (modelValue) {
               return modelValue(); 
            });

            ngModel.$parsers.push(function (viewValue) {
               ngModel.$modelValue(viewValue);
               return ngModel.$modelValue;
            });
        }
    };
});

You can check the example in jsFiddle or Plunker.

As you can see, the formatter/parser thing works just fine, but the problem is that the <input> value of the property that is internally modified (say bar if you changed foo) is not updated.

I can't even grasp why in earth is not working. As you can see in the example, below each input I'm interpolating the same value which seems perfectly updated upon any change. Why ng-model isn't updating my <input> value?

Share Improve this question asked May 30, 2013 at 3:59 dariofarzatidariofarzati 8,6466 gold badges31 silver badges28 bronze badges 1
  • 1 $formatters run "whenever the model value changes." My guess is that $modelValue never changes--it remains a static constant reference to foo() or bar(). You call the function to change an internal representation of some data, but the thing that ngModel is attached to never changes. The DOM updates because the binding to foo() and bar()--the results of those function calls--do update. – Michelle Tilley Commented May 30, 2013 at 5:03
Add a ment  | 

2 Answers 2

Reset to default 4

This is one way you could do it:

http://plnkr.co/edit/7HCpSb?p=preview

(It looks a kind of hacky and I do not like my solution very much, though.)

As @Brandon pointed out, you are watching the getter function. The function evaluation may give different values, but function definition never changes in your example, so formatter never fires in your directive.

In my example, I'm watching the evaluation of the getter function, so it fires whenever internal value changes. I avoided using ngModel as it does not look fit in this way.

in the template:

<input my-directive accessor="myobj.foo">

in the directive link function:

$scope.$watch( $attrs.accessor + '()', function( v ) {
  if ( v ) $element[0].value = v;
});

I could get a getter/setter scenario to work by coding another directive besides of ng-model for specifying the getter and the setter of a ng-model binding. See:

https://stackoverflow./a/21290588/738808

Using the ng-model-getter and ng-model-setter directives described in this question, you would just proceed this way in your html:

<input my-directive ng-model="$foo" ng-model-getter="myobj.foo()" ng-model-setter="myobj.foo($value)">
<input my-directive ng-model="$bar" ng-model-getter="myobj.bar()" ng-model-setter="myobj.bar($value)">

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744740044a4590972.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信