angularjs中有没有一种方法可以动态设置ngModel



我有一个组件(一个具有隔离作用域的指令),它将对象列表映射到允许修改该对象的一个属性的输入列表。

但我想让这个组件具有通用性。所以它应该接受列表中每个对象的深度嵌套属性的路径,该列表应该绑定到输入。

例如,我们有一个人员列表,每个人都有用不同语言说出的名字:

var people = [
  {
    age: 31,
    multilang_attributes: {
      en: {name: 'John'},
      ru: {name: 'Иван'}
    }
  },
  {
    age: 29,
    multilang_attributes: {
      en: {name: 'Peter'},
      ru: {name: 'Пётр'}
    }
  },
];

我想将我的通用组件应用于以下人员列表:

<input-list
  items="people",
  item-model="multilang_attributes[locale].name"
></input-list>

我尝试用&创建作用域属性,这将允许我在父作用域中执行表达式,然后将该表达式传递给ngModel,但这不起作用。你可以在plunkr中看到这个尝试。

如何看待这项任务?

一个选项是$parse访问器字符串,并为模型使用getter/setter。为此:


  1. 将指令html更改为:

    item-accessor="'multilang_attributes.' + app.locale + '.name'"

    这将使类似multilang_attributes.en.name的内容可用。


  1. 将指令代码更改为:

    app.directive('inputList', function () {
      return {
        restrict: 'E',
        scope: {
          items: '=',
          itemAccessor: '='
        },
        template: '<ul><li ng-repeat="item in items"><input ng-model="getModel(item)" ng-model-options="{ getterSetter: true }" /></li></ul>',
        controller: function ($scope, $parse) {
          $scope.getModel = function(item) {
            return function (newValue) {
              var getter = $parse($scope.itemAccessor);
              if (arguments.length > 0) {
                getter.assign(item, newValue);
              }
              return getter(item);
            };
          };
        }
      };
    });
    

外部演示:http://plnkr.co/edit/VzFrBxNcsA5BarIVr6oG?p=preview

var app = angular.module('TestApp', [])
app.controller('AppCtrl', function AppController() {
    
  this.locales = ['en', 'fr']
  this.locale = 'en';
  
  this.people = [
    {
      age: 31,
      multilang_attributes: {
        en: {name: 'John (en)'},
        fr: {name: 'John (fr)'}
      }
    },
    {
      age: 29,
      multilang_attributes: {
        en: {name: 'Fred (en)'},
        fr: {name: 'Fred (fr)'}
      }
    },
  ];
  
});
  
app.directive('inputList', function () {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      itemAccessor: '='
    },
    template: '<ul><li ng-repeat="item in items"><input ng-model="getModel(item)" ng-model-options="{ getterSetter: true }" /></li></ul>',
    
    controller: function ($scope, $parse) {
      
      $scope.getModel = function(item) {
        return function (newValue) {
          var getter = $parse($scope.itemAccessor);
          
          if (arguments.length > 0) {
            getter.assign(item, newValue);
          }
          
          return getter(item);
        };
      };
    }
  };
});
<!DOCTYPE html>
<html>
  <head>
    <script data-require="angular.js@1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
  </head>
  <body ng-app="TestApp" ng-controller="AppCtrl as app">
    <div class="container">
      <select ng-model="app.locale" ng-options="v as v for v in app.locales"></select>
      <hr>
      
      <input-list
        items="app.people"
        item-accessor="'multilang_attributes.' + app.locale + '.name'"
      ></input-list>
      
      <hr>
      <pre>{{ app.people|json }}</pre>
    </div>
  </body>
</html>


注意 您应该合理地使用正确的注入语法和controllerAs/bindToController

最新更新