角度绑定为对象

Angular bind as object

本文关键字:对象 绑定      更新时间:2023-09-26

为澄清目的重新表述问题。

Plunkr
视图:

<input type="text" ng-model="form['data']['sampleData']">
    <input type="text" ng-model="form[bindingPrefix][bindingSuffix]">
    <input type="text" ng-model="form[bindingValue]">

控制器:

    $scope.form = {
    data: {
      sampleData: '123'
    }
  };
  $scope.bindingValue = 'data.sampleData';
  $scope.bindingPrefix = 'data';
  $scope.bindingSuffix = 'sampleData';

期望效果:我希望form[bindingValue]能产生与form[bindingPrefix][bindingSuffix]一样的效果,而无需特意将bindingValue分离为bindingPrefixbindingSuffix,因为bindingValue可以是数组中的动态值,如data.sampleData.childDatadata.sampleData.childData.childChildData,用于ng重复模型。

p/S:bindingValue是从服务器端传来的东西,我无法控制它。

==========================================================================可能在这里的这个混蛋那里工作。理想情况下,不应修改视图。点击此处

即使路径可以是可变长度的,我们也可以将问题减少到只使用一个变量的路径。只要你不破坏数据对象的结构,这就应该有效(或者如果你破坏了,记得再次运行这个准备代码)。

所以我们有数据

$scope.form = {
    data: {
      sampleData: '123'//This could be even deeper in the object, can't know for sure
    }
};

但我们需要保持CCD_ 8和包含对象之间链接的唯一变量名称是最后一个。"sampleData"。如果我们只获得对data obejct和"sampleData"属性名称的引用,那么所有其他属性名称都可以被丢弃。

控制器内:

//Get the path from the server, split it to create an array of property names
var path = 'data.sampleData'.split('.');
//We'll start changing these soon
var prevValue = $scope.form, nextValue;
for(var i = 0; i < path.length - 1; i++){//Note that we are not looping all the way through (-1)!
    //Get all the properties one by one
    nextValue = prevValue[path[i]];
    if(nextValue == undefined){
        //This is an error, the data didn't conain the property that it was supposed to.
        //It's up to you how to handle this. Doing the following will add the missing properties and keep things working.
        nextValue = prevValue[path[i]] = {};
    }
    //The prevValue will first be $scope.form, then form.data
    prevValue = nextValue;
 }
 //$scope.bindingContainer is a reference to $scope.form.data object
 $scope.bindingContainer = prevValue;
 //$scope.bindingValue is the last property name, "sampleData"
 $scope.bindingValue = path[path.length-1];

在模板中:

<input type="text" ng-model="bindingContainer[bindingValue]">

一切都应该正常(再说一遍,只要你不改变$scope.form.data = somethingElse)。

当然,我们有点作弊,因为现在模板根本没有引用原始的$scope.form对象。不过,这并不重要,因为它引用了data对象及其属性"sampleData",所以只要$scope.form引用了相同的data对象,我们就可以获得所需的一切。

我创建了一个名为my-dynamic-model的指令,它被<input>元素引用。这包含对作用域变量$parsed的引用,以引用正确的$scope.bindingValue数组。

请参阅所附的工作plunkr

现在,您可以将$scope.bindingValue中的层次结构指定为所需的深度,它将正确更新$scope变量。只需确保它是一个完整的$scope对象层次结构路径。

代码:

var app = angular.module('app', []);
app.controller('MyController', function($scope) {
  $scope.form = {
    data: { 
      sampleData: '1234',
      sampleData1: {
        sampleData2: '2345'
      }
    }
  };
  $scope.bindingValue = ['form.data.sampleData', 'form.data.sampleData1.sampleData2'];
});

app.directive('myDynamicModel', function( $parse, $log ) {
    return function( scope, el, attrs ) {
        var model = $parse( attrs.myDynamicModel );
        var finalModel = $parse(model(scope));
        finalModel.assign(scope, finalModel(scope));
        scope.$apply();
        el.bind('keyup', function() {
            finalModel.assign(scope, el.val());
            if (!scope.$$phase) scope.$apply();
        })
    }
});

HTML:

<div ng-controller="MyController">
    <input type="text" ng-model="form.data.sampleData" my-dynamic-model="bindingValue[0]" placeholder="Update me">
    <input type="text" ng-model="form.data.sampleData1.sampleData2" my-dynamic-model="bindingValue[1]" placeholder="Update me too">
  <div>{{ form.data.sampleData }}</div>
  <div>{{ form.data.sampleData1.sampleData2 }}</div>
</div>

或者这可能与您当前使用angular、,这里还有一篇关于控制器语法的优秀文章。

function ExampleCtrl($scope) {
    $scope.bindingValue = data.sampleData;
    $scope.bindingPrefix = 'data';
    $scope.bindingSuffix = 'sampleData';
  }
  // Controller or Controller as syntax is a reference the controller just a short-hand name.
<body ng-app="ExampleApp">
  <div class="example" ng-controller="ExampleCtrl">
    <input type="text" ng-model="bindingValue">
  </div>
</body>

试试这样的东西,也许有一些语法差异:

function ExampleCtrl() {
  var ctrl = this;
  ctrl.bindingValue = data.sampleData;
  ctrl.bindingPrefix = 'data';
  ctrl.bindingSuffix = 'sampleData';
}
<body ng-app="ExampleApp">
  <div class="example" ng-controller="ExampleCtrl as ctrl">
    <input type="text" ng-model="ctrl.bindingValue">
  </div>
</body>

在控制器中,创建一个范围对象,如下所示:

$scope.data = {
    sampleData: {
        childSampleData: null
    },
    anotherItem: null,
    moreData: {
        Child1: null,
        Child2: null
    }
}

您的HTML应该引用这样的范围对象:

<input type="text" ng-model="data.sampleData.childSampleData">
<input type="text" ng-model="data.anotherItem">
<input type="text" ng-model="data.moreData.Child1">
<input type="text" ng-model="data.moreData.Child1">

不幸的是,您不能像代码显示的那样引用ngModel。所以说ng-model="form[bindingPrefix][bindingSuffix]"是不正确的,因为您不能访问这里的form对象。但是,您可以像我在HTML中那样使用点符号来访问子对象。

如果你不确定哪个ngModel需要更新,你应该使用这样的函数:

<input type="text" ng-model="item1" ng-change="updateModel()">
$scope.updateModel = function() {
    $scope.data[bindingPrefix][bindingSuffix] = $scope.item1;
}