Làm cách nào để xóa một mục khỏi một mảng trong phạm vi AngularJS?


153

Danh sách việc cần làm đơn giản, nhưng có nút xóa trên trang danh sách cho từng mục:

nhập mô tả hình ảnh ở đây

HTML mẫu có liên quan:

<tr ng-repeat="person in persons">
  <td>{{person.name}} - # {{person.id}}</td>
  <td>{{person.description}}</td>
  <td nowrap=nowrap>
    <a href="#!/edit"><i class="icon-edit"></i></a>
    <button ng-click="delete(person)"><i class="icon-minus-sign"></i></button>
  </td>
</tr>

Phương pháp điều khiển có liên quan:

$scope.delete = function (person) {
  API.DeletePerson({ id: person.id }, function (success) {
    // I need some code here to pull the person from my scope.
  });
};

Tôi đã thử $scope.persons.pull(person)$scope.persons.remove(person).

Mặc dù cơ sở dữ liệu đã xóa thành công, tôi không thể kéo mục này khỏi phạm vi và tôi không muốn thực hiện cuộc gọi phương thức đến máy chủ để lấy dữ liệu mà khách hàng đã có, tôi chỉ muốn xóa người này khỏi phạm vi.

Có ý kiến ​​gì không?


Tôi chạy tuyến đường whit $ này và chế độ xem sẽ không hoạt động tốt. Tôi luôn có một trang trống sau khi tôi xóa :-(
zx1986


Đây không phải là quá nhiều về việc xóa khỏi phạm vi mà là từ một mảng, và nó sẽ giống nhau bất kể góc cạnh, nó chỉ là javascript
Xsmael

Câu trả lời:


259

Vấn đề của bạn không thực sự xảy ra với Angular, mà là với các phương thức Array. Cách thích hợp để loại bỏ một mục đặc biệt khỏi một mảng là với Array.splice. Ngoài ra, khi sử dụng ng-repeat, bạn có quyền truy cập đặc biệt$index , là chỉ mục hiện tại của mảng bạn đã truyền vào.

Giải pháp thực sự khá đơn giản:

Lượt xem:

<a ng-click="delete($index)">Delete</a>

Điều khiển:

$scope.delete = function ( idx ) {
  var person_to_delete = $scope.persons[idx];

  API.DeletePerson({ id: person_to_delete.id }, function (success) {
    $scope.persons.splice(idx, 1);
  });
};

1
@ScottMalachowski Bạn nói đúng. Tôi quên mất phần đó. Tôi đã sửa đổi câu trả lời của mình để phản ánh điều đó, vì vậy nó sẽ phù hợp với câu trả lời của bạn.
Josh David Miller

13
Cẩn thận - giải pháp dựa trên chỉ mục này sẽ không hoạt động nếu bạn sử dụng nhiều lần lặp lại của cùng một đối tượng trong một chế độ xem (ví dụ: Nhiệm vụ theo lịch trình, Nhiệm vụ không được quy định, Nhiệm vụ đã hoàn thành xuất phát từ $ scope.t Nhiệm vụ) bởi vì bạn sẽ có nhiều mục với chỉ số 2, 3, 4, v.v.
shacker

Nhận xét ở trên, bởi @shacker, về nhiều lần lặp ng với các bộ lọc khác nhau của cùng một mảng, là đúng. Sử dụng phương pháp bên dưới với indexOf
Andrew Kuklewicz

4
@AndrewKuklewicz - indexOfcó thể là một hoạt động đắt tiền hơn; không lọc, nó hoàn toàn không cần thiết Nhưng với lọc, indexOfsẽ là phương pháp thích hợp.
Josh David Miller

Tôi đang vật lộn với điều này và đã phải thực hiện một thay đổi nhỏ đối với việc tạo thẻ ở trên - đang - xóa ({{$ index}}) với {{}} nếu không tôi đã nhận được chuỗi $ index - NHƯNG tôi có lỗi không bao giờ gọi phương thức đó Nó thực hiện khi tôi xóa bất kỳ đề cập nào về chỉ mục như xóa () nhưng điều đó không thực sự hữu ích.
mikemil

310

Bạn sẽ phải tìm chỉ mục của mảng persontrong personsmảng của mình , sau đó sử dụng splicephương thức của mảng :

$scope.persons.splice( $scope.persons.indexOf(person), 1 );

49
đây là một câu trả lời tốt hơn; hoạt động khi danh sách đã được lọc để chỉ mục trong chế độ xem không giống như trong mảng trong phạm vi.
Andrew Kuklewicz

5
Đây thực sự là câu trả lời tốt hơn. Lưu ý rằng ngoài trường hợp sử dụng danh sách được lọc được đề cập bởi Andrew, cách tiếp cận này cũng bao gồm trường hợp bạn xóa nhiều người và các yêu cầu Ajax cho các lần xóa này không theo thứ tự. Nếu bạn đã sử dụng các chỉ mục hàng từ trước khi trả về cuộc gọi Ajax, cuối cùng bạn sẽ xóa các hàng sai.
Joris

4
Trong một số trường hợp tốt hơn, nhưng với indexOf, bạn phải lặp đi lặp lại tất cả các mục để tìm đúng mục, trong câu trả lời Josh, bạn nhận được chỉ mục và mục nhanh hơn
daver

@mike - Sử dụng polyfill này .
Joseph Silber

8

Tôi sẽ sử dụng thư viện Underscore.js có danh sách các hàm hữu ích.

without

without_.without(array, *values)

Trả về một bản sao của mảng với tất cả các phiên bản của các giá trị bị xóa.

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
// => [2, 3, 4]

Thí dụ

var res = "deleteMe";

$scope.nodes = [
  {
    name: "Node-1-1"
  },
  {
    name: "Node-1-2"
  },
  {
    name: "deleteMe"
  }
];
    
$scope.newNodes = _.without($scope.nodes, _.findWhere($scope.nodes, {
  name: res
}));

Xem bản trình diễn trong JSFiddle .


filter

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });

// => [2, 4, 6]

Thí dụ

$scope.newNodes = _.filter($scope.nodes, function(node) {
  return !(node.name == res);
});

Xem bản demo trong Fiddle .


Tôi có lẽ muốn sử dụng $scope.nodes = _.without($scope.nodes, node);vì anh có tham chiếu đếnnode
jake

Trên các trình duyệt hiện đại, bạn có thể sử dụng Array.prototype.filter. _.filter(array, fun)trở thành array.filter(fun).
bfontaine

7
$scope.removeItem = function() {
    $scope.items.splice($scope.toRemove, 1);
    $scope.toRemove = null;
};

cái này hiệu quả với tôi


4

Nếu bạn có bất kỳ chức năng nào liên quan đến danh sách, khi bạn thực hiện chức năng ghép nối, liên kết cũng bị xóa. Giải pháp của tôi:

$scope.remove = function() {
    var oldList = $scope.items;
    $scope.items = [];

    angular.forEach(oldList, function(x) {
        if (! x.done) $scope.items.push( { [ DATA OF EACH ITEM USING oldList(x) ] });
    });
};

Danh sách param được đặt tên các mục . Các param x.done cho biết nếu mục sẽ bị xóa.

Một tài liệu tham khảo khác: Một ví dụ khác

Hy vọng giúp bạn. Lời chào hỏi.


2

Đối với câu trả lời được chấp nhận của @Joseph Silber không hoạt động, vì indexOf trả về -1. Điều này có thể là do Angular thêm một hashkey, khác với $ scope.items [0] và mục của tôi. Tôi đã cố gắng giải quyết vấn đề này bằng hàm angular.toJson (), nhưng nó không hoạt động :(

À, tôi đã tìm ra lý do ... Tôi sử dụng phương pháp chunk để tạo hai cột trong bảng bằng cách xem $ scope.items của tôi. Lấy làm tiếc!


2

Bạn cũng có thể sử dụng cái này

$scope.persons = $filter('filter')($scope.persons , { id: ('!' + person.id) });

1

Angular có một hàm dựng sẵn được gọi arrayRemove, trong trường hợp của bạn, phương thức có thể chỉ đơn giản là:

arrayRemove($scope.persons, person)


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.