【问题标题】:ng-model as a variable in a bidimensional arrayng-model 作为二维数组中的变量
【发布时间】:2013-10-18 01:30:32
【问题描述】:
  <p ng-repeat="row in matrix">
    <span ng-repeat="column in row">
      <input type="text" style="width: 20px; text-align: center;" ng-model="column" ng-change="{{column = }}">
    </span>
  </p>

在我的控制器上:

$scope.matrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];

我有一小段代码,我希望那个小文本输入框与matrix[i][u] 相关联。我知道我可以使用ng-model= 使文本框与某个变量相关联。

但是,我希望它是双向的 - 更改变量将更改文本框值,更改文本框值将更改变量。但是,当我在输入文本框上有 ng-model 时,我似乎无法编辑它的值,因为它总是会“重置”为默认值。

我知道我可以使用ng-change,但我做了中间线:

<input type="text" style="width: 20px; text-align: center;" ng-model="column" ng-change="update">

而且调用 $scope.update() 函数也不起作用。我仍然无法编辑文本框的值。

tl;dr:我怎样才能有一个带有ng-model 的文本框并允许对其进行编辑以编辑文本框值和 ng-model 上的变量。

【问题讨论】:

  • stackoverflow.com/questions/15720334/… 我现在发现了,但根据那个我的应该也可以工作。
  • 我在该问题/答案中看不到任何表明您的解决方案应该有效的内容。这里的问题是每个ng-repeat 都会创建一个子作用域,如果您最终处于变量的“标量”级别,这将创建与其父级断开连接的变量。
  • 再次重申:此处所写和显示的内容不适用于此处。该问题并不表明您的代码应该可以工作。
  • 一个工作的原因是因为那些是对象,你刚刚得到整数。如果你有实际的对象,这将在没有 $index 或任何东西的情况下工作。

标签: angularjs


【解决方案1】:

这样使用:

<input type="text" ng-model="matrix[$index][$parent.$index]" style="width: 20px; text-align: center;" />

示例:http://jsfiddle.net/cherniv/hcLVE/

它不是很优雅,但它正在工作..

【讨论】:

  • 我怀疑row[$index] 也会起作用。另外:您的两个索引不是顺序错误吗?后一个索引是“内部”索引,所以不应该是matrix[$parent.$index][$index]吗?
  • 不,你实际上证明了我的观点。第一个参数[0] 明确引用外部数组,第二个参数[2] 引用内部数组。因此结果是 2。所以它是 [outer][inner],因此需要是 [$parent.$index][$index],因为这里的父索引是外部数组。
  • 感谢您证明我的怀疑。这实际上是有道理的。让我解释一下:这里的事情是,在内部循环中,我们最终得到了一个标量变量 (column),它只是在内部 ng:repeat 设置范围时被复制。在外部ng:repeat 上,这不是问题,因为row 仍然不是标量变量,而是一个复杂对象(数组),它将通过引用复制,因此副本不会与原始对象断开连接。
  • @kju ,可能是我累了,但我在这里看不到任何错误:jsfiddle.net/cherniv/A5X9w
  • 这是因为您的输出代码也交换了两个索引。尝试只输出{{matrix}}你会看到。
【解决方案2】:

这是一个更有趣的指令方法:

app.directive("matrix", function($compile){
 return{
 scope:{
   ngModel:'='
 },
 restrict:"E",
 link:function(scope, element, attributes){
   var render = function(){
    var template="";
    scope.ngModel.forEach(function(row, r){
      template+="<p>";
      console.log(scope.ngModel[r]);
      row.forEach(function(column, c){
        template+='<span><input style="width: 20px; text-align: center;" ng-model="ngModel['+r+']['+c+']"></span>';
      });
      template+="</p>";
    });
    element.html(template);
    $compile(element.contents())(scope);
  }
  render();
  scope.$watch('ngModel', render, true);
 }
}
});

可以使用&lt;matrix ng-model="matrix"&gt;&lt;/matrix&gt;

只是因为我喜欢指令。跑到这里:http://plnkr.co/edit/jI7Hi9LKXnDFBd0gXtNZ?p=preview

【讨论】:

    【解决方案3】:

    使用

    row[$index]
    

    作为输入标签中的ng:model

    <input type="text" ng-model="row[$index]" style="width: 20px; text-align: center;" />
    

    这工作和使用column 不起作用的原因是:&lt;input&gt; 标签将通过复制父作用域来创建一个子作用域。但是column 是一个简单/标量变量。这样的变量实际上只会被复制。因此,您最终会得到ng:model 中的副本,该副本未连接到矩阵中的实变量。这就是为什么 AngularJS 的人强调你应该总是有一个带有ng-model 引用的点的东西。

    另一方面,row 仍然是一个复变量(数组),而不是一个标量。 JavaScript 不是通过创建真正的副本而是通过复制对数据的引用来“复制”这样的变量。因此,您最终会获得对相同数据的第二次引用。因此,&lt;input&gt; 标签创建的子作用域中的row 仍然连接到矩阵中的原始行数据,并且双向数据绑定将起作用。

    再次强调这一点:永远不要使用没有点的东西作为ng:model。 AngularJS 曾经在他们的网页上有过这样做的不好的例子,但似乎它们大部分/全部都被改变了。但是正如你在这个例子中看到的那样,foo[5] 也可以,因为它仍然引用了一个复杂的变量。 foo["bar"] 实际上等于 foo.bar

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 1970-01-01
      • 2021-01-31
      相关资源
      最近更新 更多