如何替换使用ng-repeat显示的数组中的对象?

时间:2022-11-25 16:14:45

I have an array of items that is displayed in a table using ng-repeat. When you click on an item, that item is pulled from the server and the table should then be updated with the updated item.

我有一系列项目使用ng-repeat显示在表格中。当您单击某个项目时,该项目将从服务器中提取,然后应使用更新的项目更新该表格。

Function to get the updated item when clicking on an item in the table:

单击表格中的项目时获取更新项目的功能:

$scope.getUpdatedItem = function(item){
    itemService.getItem(item).then(
        function(updatedItem){
            item = updatedItem;
        },
        function(error){
            //Handle error
        }
    );
};

I'm displaying the items using:

我正在使用以下方式显示项目:

<tr ng-repeat="item in myItems">

The problem: The item in the table is never updated.

问题:表中的项永远不会更新。

What's the best way to update the item in the ng-repeat? Can i use "track by $index" in the ng-repeat for this? Or do I have to iterate over myItems to find the item I want to replace?

更新ng-repeat中项目的最佳方法是什么?我可以在ng-repeat中使用“追踪$ index”吗?或者我是否必须迭代myItems才能找到我要替换的项目?

Update:

更新:

A possible solution is instead of using

可能的解决方案是使用而不是使用

item = updatedItem,

item = updatedItem,

to use:

使用:

var index = $scope.myItems.indexOf(item);
$scope.myItems[index] = updateItem;

However, I feel that there should be a "cleaner" way of doing this.

但是,我觉得应该采用“更清洁”的方式来做到这一点。

4 个解决方案

#1


14  

There isn't a much cleaner way (then your update). As you noticed, when you change item in your callback function you change the local reference, and not the original item in the array.

没有更清洁的方式(然后你的更新)。正如您所注意到的,当您更改回调函数中的项目时,您更改了本地引用,而不是数组中的原始项目。

You can improve this a bit by using the $index from the ng-repeat, instead of calculating it yourself:

你可以使用ng-repeat中的$ index来改善这一点,而不是自己计算:

<div ng-click="getUpdatedItem(item, $index)"> </div>

And in your controller:

在你的控制器中:

$scope.getUpdatedItem = function(item, index){
    itemService.getItem(item).then(
    function(updatedItem){
        $scope.myItems[index] = updateItem;
    },
    function(error){
        //Handle error
    }
    );
};

You can also use angular.copy instead but it's much less efficient:

您也可以使用angular.copy,但效率要低得多:

function(updatedItem){
    angular.copy(updateItem, item);
},

#2


2  

If I understand your problem properly

如果我理解你的问题

could something like this work?

有可能像这样的工作吗?

<!-- template code -->
<table>
    ...
    <tr ng-repeat="(index, item) in items">
        <td>{{item.name}}</td>
        <td>
             {{item.detail}}
             <button ng-if="!item.detail" ng-click="loadItem(index)">
        </td>
    </tr>
</table>

// Controller Code
$scope.items = [...]
$scope.loadItem = function(index){
    itemService.getItemDetail($scope.items[index]).then(function(itemDetail){
        $scope.items[index].detail = itemDetail;
    });
};

#3


1  

item may start as a reference to an item in your list, but when you say:

item可以作为对列表中项目的引用开始,但当您说:

item = updatedItem;

You reseat that binding -- you are no longer referring to the item in the list, but to the disconnected one that was returned in your promise. Either you will need to modify the item, like so:

您重新安装该绑定 - 您不再引用列表中的项目,而是指您的承诺中返回的已断开连接的项目。您需要修改项目,如下所示:

function(updatedItem){
  item.varA = updatedItem.varA
  item.varB = updatedItem.varB
  ...
}

Or, if it gets too hairy, you might consider an item array that looks more like this:

或者,如果它太毛茸茸,你可能会考虑一个看起来更像这样的项目数组:

var items = [ 
  { data: item1 },
  { data: item2 },
  { data: item3 }
};

At which point your update function will look like this:

此时您的更新功能将如下所示:

function(updatedItem){
    item.data = updatedItem;
},

#4


0  

I've just spent hours on this issue. I couldn't use the $index solution from @eladcon, as my ng-repeat also used a filter, to the index isn't correct if the rows/items are filtered.

我刚刚在这个问题上花了好几个小时。我无法使用@eladcon的$ index解决方案,因为我的ng-repeat也使用过滤器,如果行/项被过滤,索引不正确。

I thought I would be able to just do this:

我以为我能做到这一点:

$filter('filter')($scope.rows, {id: 1})[0] = newItem;

but that doesn't work.

但这不起作用。

I ended up iterating the array until I found a match, and then using the $index from the iteration (not from the ng-repeat) to set the array item to the new item.

我最终迭代了数组,直到找到匹配,然后使用迭代中的$ index(而不是ng-repeat)将数组项设置为新项。

// i'm looking to replace/update where id = 1
angular.forEach($scope.rows, function(row, $index) {
  if (row.id === 1) {
    $scope.rows[$index] = newItem;
  }
})

See here: https://codepen.io/anon/pen/NpVwoq?editors=0011

请参见此处:https://codepen.io/anon/pen/NpVwoq?edit = 0011

#1


14  

There isn't a much cleaner way (then your update). As you noticed, when you change item in your callback function you change the local reference, and not the original item in the array.

没有更清洁的方式(然后你的更新)。正如您所注意到的,当您更改回调函数中的项目时,您更改了本地引用,而不是数组中的原始项目。

You can improve this a bit by using the $index from the ng-repeat, instead of calculating it yourself:

你可以使用ng-repeat中的$ index来改善这一点,而不是自己计算:

<div ng-click="getUpdatedItem(item, $index)"> </div>

And in your controller:

在你的控制器中:

$scope.getUpdatedItem = function(item, index){
    itemService.getItem(item).then(
    function(updatedItem){
        $scope.myItems[index] = updateItem;
    },
    function(error){
        //Handle error
    }
    );
};

You can also use angular.copy instead but it's much less efficient:

您也可以使用angular.copy,但效率要低得多:

function(updatedItem){
    angular.copy(updateItem, item);
},

#2


2  

If I understand your problem properly

如果我理解你的问题

could something like this work?

有可能像这样的工作吗?

<!-- template code -->
<table>
    ...
    <tr ng-repeat="(index, item) in items">
        <td>{{item.name}}</td>
        <td>
             {{item.detail}}
             <button ng-if="!item.detail" ng-click="loadItem(index)">
        </td>
    </tr>
</table>

// Controller Code
$scope.items = [...]
$scope.loadItem = function(index){
    itemService.getItemDetail($scope.items[index]).then(function(itemDetail){
        $scope.items[index].detail = itemDetail;
    });
};

#3


1  

item may start as a reference to an item in your list, but when you say:

item可以作为对列表中项目的引用开始,但当您说:

item = updatedItem;

You reseat that binding -- you are no longer referring to the item in the list, but to the disconnected one that was returned in your promise. Either you will need to modify the item, like so:

您重新安装该绑定 - 您不再引用列表中的项目,而是指您的承诺中返回的已断开连接的项目。您需要修改项目,如下所示:

function(updatedItem){
  item.varA = updatedItem.varA
  item.varB = updatedItem.varB
  ...
}

Or, if it gets too hairy, you might consider an item array that looks more like this:

或者,如果它太毛茸茸,你可能会考虑一个看起来更像这样的项目数组:

var items = [ 
  { data: item1 },
  { data: item2 },
  { data: item3 }
};

At which point your update function will look like this:

此时您的更新功能将如下所示:

function(updatedItem){
    item.data = updatedItem;
},

#4


0  

I've just spent hours on this issue. I couldn't use the $index solution from @eladcon, as my ng-repeat also used a filter, to the index isn't correct if the rows/items are filtered.

我刚刚在这个问题上花了好几个小时。我无法使用@eladcon的$ index解决方案,因为我的ng-repeat也使用过滤器,如果行/项被过滤,索引不正确。

I thought I would be able to just do this:

我以为我能做到这一点:

$filter('filter')($scope.rows, {id: 1})[0] = newItem;

but that doesn't work.

但这不起作用。

I ended up iterating the array until I found a match, and then using the $index from the iteration (not from the ng-repeat) to set the array item to the new item.

我最终迭代了数组,直到找到匹配,然后使用迭代中的$ index(而不是ng-repeat)将数组项设置为新项。

// i'm looking to replace/update where id = 1
angular.forEach($scope.rows, function(row, $index) {
  if (row.id === 1) {
    $scope.rows[$index] = newItem;
  }
})

See here: https://codepen.io/anon/pen/NpVwoq?editors=0011

请参见此处:https://codepen.io/anon/pen/NpVwoq?edit = 0011