Using expressions in ngModel in Angular.js

六月ゝ 毕业季﹏ 提交于 2019-12-12 07:49:12

问题


Giving the code inside of my controller:

$scope.entity = {
  firstName: 'Jack',
  lastName: 'Bauer',
  location: {
    city: 'New York'
  }
};
$scope.path = 'location.city';

How do I dynamically bind ngModel to the property of the entity specified by path?

I've tried something like this, but to no avail:

<input ng-model="'entity.' + path">

回答1:


Slava, I'm not too sure if this is a good idea to begin with. But anyhow, You need to make your model getterSetter aware by adding this property to your input ng-model-options="{ getterSetter: true }. Then you need a function in your controller that builds a getterSetter out of a sting.

<input type="text" ng-model="propertify('entity.' + path)" ng-model-options="{ getterSetter: true }">

That's how the resulting template would look.

Luckily angular has an $parse service that makes this a lot easier. so something like this would need to be in your controller, or even better in a injected service.

  $scope.propertify = function (string) {
      var p = $parse(string);
      var s = p.assign;
      return function(newVal) {
          if (newVal) {
              s($scope,newVal);
          }
          return p($scope);
      } ;
  };

That will return a getter-setter function that handles this for you. see it in action in this plunk




回答2:


Update

It's not working as expected, the value is displayed correctly, but can not be changed. The correct solution is provided by Sander here.


Incorrect solution

Wow, solved it accidentally:

<input type="text" ng-model="$eval('entity.' + path)">

And here's the Plunk.

I hope it will help someone.




回答3:


You could use the bracket notation with a little modification, as you want to bind to a nested property. You have to split the path to the property:

<input ng-model="entity[locationKey][cityKey]"/>

Controller:

$scope.locationKey = 'location';
$scope.cityKey = 'city';

See js fiddle




回答4:


After reading and using Sander Elias' answer, I was using this, but ran into another problem.

When combining his result with ng-required="true" in the <input> you could not empty the field, because when the field would be empty, the newVal is passed as undefined.

After some more research, I found an isssue on GitHub that addresses and solves this problem.

Here is what Sander's and the GitHub answer combined look like:

$scope.propertify = function (string) {
    var property = $parse(string);
    var propAssign = property.assign;
    return function (newVal) {
        if (arguments.length) {
            newVal = angular.isDefined(newVal)?  newVal : '';
            propAssign($scope, newVal);
        }
        return property($scope);
    };
};

The argument.length reflects the number of values that are passed to the getter/setter and will be 0 on a get and 1 on a set.

Besided that, I added the angular.isDefined() as Sumit suggested in a comment to also save false and empty ("") values.

Here is an updated Plunker



来源:https://stackoverflow.com/questions/33153769/using-expressions-in-ngmodel-in-angular-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!