Search code examples
angularjsmatrixdata-binding

angularjs multidimensional array data binding


I want to display & bind value on input form based on multidimensional array [matrix] using angularjs. this is js function I use to generate array and variable for save the result

 function getMatrix(rows, cols, defaultValue){
  var arr = new Array(rows);
  for (var i = 0; i < rows; i++) {
    arr[i] = new Array(cols);
    for (var j = 0; j < cols ; j++) {
      if(defaultValue !== null){
        arr[i][j] = defaultValue;
      }
      else{
        arr[i][j] = {"value":i+"-"+j};
      }
    };
  };
  return arr;
}

$scope.data = getMatrix(3,3,getMatrix(2,3,null));

and here's the html table for displaying data

<table>
 <tr ng-repeat="row in data">
  <td ng-repeat="cell in row track by $index">
    <table>
      <tr ng-repeat="deepRow in cell">
        <td ng-repeat="deepCell in deepRow track by $index">
            <input type="text" style="width: 20px;" ng-model="deepCell.value">
        </td>
      </tr>
    </table>
   </td>
  </tr>
</table>

when I display & bind in normal n x n array, everything works good, but when I try to create & bind nested multidimensional array, it doesn't works as expected. when I change value in deep array, value with same row will changed too.

Here's the code on plunker. Multidimensional Array Binding

Am I missing something here?


Solution

  • The issue will be illuminated if you change the second argument to getMatrix(1, 1, null). This shows you pretty clearly that the element in the array is always the same. And of course it is, you said it was the default value.

    To prevent this issue, you need to call getMatrix(2, 3, null) for every cell. So perhaps defaultValue should be a function that produces the default value instead. That's one way to do it. See this edit of your plunkr:

    http://plnkr.co/edit/oPCBOcfBiAxwtwNhr6vp?p=preview

    // Code goes here
    angular.module('MatrixApp', [])
    .controller('MatrixCtrl', ['$scope',
      function($scope) {
    
        function getMatrix(rows, cols, defaultValueFn){
          var arr = new Array(rows);
          for (var i = 0; i < rows; i++) {
            arr[i] = new Array(cols);
            for (var j = 0; j < cols ; j++) {
              if(defaultValueFn !== null){
                arr[i][j] = defaultValueFn();
              }
              else{
                arr[i][j] = {"value":i+"-"+j};
              }
            };
          };
          return arr;
        }
        var defaultX = 3;
        var defaultY = 2;
        var defaultVal = null;
        $scope.matrixDefaultFn = function() {
          return getMatrix(defaultX, defaultY, defaultVal)
        }
        $scope.data = getMatrix(3,3, $scope.matrixDefaultFn);
      }
    ]);