角绑定作为对象

时间:2016-05-03 21:49:45

标签: javascript angularjs

为了澄清目的而重述问题。

Plunkr
查看:

AppDelegate

控制器:

<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]分隔为bindingValuebindingPrefix,因为bindingValue可能是动态值,例如{{1}数组中的{},bindingSuffix用于ng-repeat模型。

P / S:bindingValue从服务器端传递,我无法控制它。

=============================================== =========================== 可以在这里使用这个plunkr工作。理想情况下,不应修改视图。Click here

4 个答案:

答案 0 :(得分:1)

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

请参阅附件 plunkr

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

<强> CODE:

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>

答案 1 :(得分:1)

即使路径可以是可变长度,我们也可以将问题简化为仅使用一个变量的路径。只要您不打破数据对象的结构(或者如果您这样做,请记住再次运行此准备代码),这应该有效。

所以我们有数据

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

但是我们需要保持sampleData和包含对象之间链接的唯一变量名称是最后一个。 &#34;的sampleData&#34 ;.如果我们只是引用data obejct和&#34; sampleData&#34;那么所有其他属性名称都可以丢弃。财产名称。

在控制器中:

//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 对象及其属性&#34; sampleData&#34;,所以只要$scope.form引用了相同 data对象我们已经得到了所有我们需要的东西。

答案 2 :(得分:0)

或者这可能与你目前使用angular写的一行有关, 这里也是一个优秀的article控制器作为语法。

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>

答案 3 :(得分:0)

在您的控制器中,创建一个这样的范围对象:

$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;
}