最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using expressions in ngModel in Angular.js - Stack Overflow

programmeradmin1浏览0评论

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">

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">
Share Improve this question asked Oct 15, 2015 at 16:27 Slava Fomin IISlava Fomin II 28.6k34 gold badges134 silver badges208 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 7

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

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.

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

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

发布评论

评论列表(0)

  1. 暂无评论