วิธีการลบรายการออกจากอาร์เรย์ในขอบเขต AngularJS


153

รายการที่ต้องทำง่าย ๆ แต่มีปุ่มลบในหน้ารายการสำหรับแต่ละรายการ:

ป้อนคำอธิบายรูปภาพที่นี่

เทมเพลต HTML ที่เกี่ยวข้อง:

<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>

วิธีการควบคุมที่เกี่ยวข้อง:

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

ฉันพยายามและ$scope.persons.pull(person)$scope.persons.remove(person)

แม้ว่าฐานข้อมูลจะถูกลบเรียบร้อยแล้วฉันไม่สามารถดึงรายการนี้ออกจากขอบเขตและฉันไม่ต้องการทำการเรียกเมธอดไปยังเซิร์ฟเวอร์สำหรับข้อมูลที่ไคลเอ็นต์มีอยู่แล้วฉันต้องการลบบุคคลนี้ออกจากขอบเขต

ความคิดใด ๆ


ฉันใช้เส้นทางเล็กน้อยนี้และมุมมองไม่ได้ผล ฉันมีหน้าว่างเสมอหลังจากลบ :-(
zx1986

ได้เขียนบทความที่คล้ายกันcodepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

นี้ไม่มากเกี่ยวกับการลบออกจากขอบเขต แต่ค่อนข้างจากอาร์เรย์และมันจะเหมือนกันโดยไม่คำนึงถึงเชิงมุมมันเป็นเพียงจาวาสคริปต์
Xsmael

คำตอบ:


259

ปัญหาของคุณไม่ได้เกี่ยวกับ Angular จริงๆ แต่ด้วยวิธี Array Array.spliceวิธีการที่เหมาะสมในการลบรายการโดยเฉพาะอย่างยิ่งจากอาร์เรย์อยู่กับ นอกจากนี้เมื่อใช้ ng-repeat คุณจะสามารถเข้าถึง$indexคุณสมบัติพิเศษซึ่งเป็นดัชนีปัจจุบันของอาร์เรย์ที่คุณส่งผ่าน

การแก้ปัญหาค่อนข้างตรงไปตรงมา:

ดู:

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

ควบคุม:

$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 คุณพูดถูก ฉันลืมส่วนนั้น ฉันแก้ไขคำตอบของฉันเพื่อสะท้อนว่ามันจะสอดคล้องกับของคุณ
Josh David Miller

13
ระวัง - โซลูชันที่อิงดัชนีนี้จะไม่ทำงานหากคุณใช้ ng-repeats ซ้ำของวัตถุเดียวกันในมุมมอง (เช่นงานที่กำหนดเวลาไว้, งานที่ไม่ได้กำหนดเวลาไว้, งานที่เสร็จสมบูรณ์แล้วทั้งหมดมาจาก $ scope.tasks) เพราะคุณจะมีหลายรายการด้วย ดัชนี 2, 3, 4, ฯลฯ
shacker

ความคิดเห็นด้านบนโดย @shacker เกี่ยวกับ ng-repeats หลายชุดพร้อมชุดตัวกรองที่แตกต่างกันของอาร์เรย์เดียวกัน ใช้วิธีการด้านล่างด้วย indexOf
Andrew Kuklewicz

4
@AndrewKuklewicz - indexOfอาจเป็นการดำเนินการที่แพงกว่า มันไม่จำเป็นเลยอย่างสมบูรณ์ แต่ด้วยการกรองindexOfจะเป็นวิธีที่เหมาะสม
Josh David Miller

ฉันกำลังดิ้นรนกับสิ่งนี้และต้องทำการเปลี่ยนแปลงเล็กน้อยในการสร้างแท็กด้านบน - การ - ลบ ({{$ ดัชนี}}) ด้วย {{}} ไม่เช่นนั้นฉันจะได้รับสตริงดัชนี $ - แต่ฉันมีบางอย่างผิดปกติเพราะมัน ไม่เคยเรียกวิธีการนั้น ทำเมื่อฉันลบการกล่าวถึงดัชนีใด ๆ เช่น delete () แต่นั่นไม่ได้ช่วยจริงๆ
mikemil

310

คุณจะต้องไปหาดัชนีของpersonคุณในpersonsอาร์เรย์แล้วใช้ของอาร์เรย์spliceวิธีการ:

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

49
นี่เป็นคำตอบที่ดีกว่า ทำงานเมื่อรายการถูกกรองเพื่อให้ดัชนีในมุมมองนั้นไม่เหมือนกับในอาร์เรย์ในขอบเขต
Andrew Kuklewicz

5
นี่เป็นคำตอบที่ดีกว่า โปรดทราบว่านอกจากรายการที่กรองแล้วจะใช้กรณีที่กล่าวถึงโดย Andrew วิธีนี้ครอบคลุมกรณีที่คุณลบหลายคนและคำขอ Ajax สำหรับการลบเหล่านี้จะส่งคืนตามลำดับ หากคุณใช้ดัชนีแถวจากก่อนที่จะโทรกลับ Ajax คุณจะต้องลบแถวที่ไม่ถูกต้องออก
Joris

4
จะดีกว่าในบางกรณี แต่มี indexOf คุณต้องย้ำผ่านรายการทั้งหมดเพื่อหาหนึ่งที่เหมาะสมในคำตอบที่จอชคุณได้รับดัชนีและรายการได้เร็วขึ้น
DAVER

@mike - ใช้polyfillนี้
Joseph Silber

8

ฉันจะใช้ไลบรารีUnderscore.jsที่มีรายการฟังก์ชันที่มีประโยชน์

without

without_.without(array, *values)

ส่งคืนสำเนาของอาร์เรย์โดยลบอินสแตนซ์ทั้งหมดของค่า

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

ตัวอย่าง

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

ดูการสาธิตในJSFiddle


filter

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

// => [2, 4, 6]

ตัวอย่าง

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

ดูการสาธิตในซอ


ฉันอาจใช้$scope.nodes = _.without($scope.nodes, node);เพราะเขาอ้างอิงถึงnode
jake

Array.prototype.filterเบราว์เซอร์ที่ทันสมัยคุณสามารถใช้ จะกลายเป็น_.filter(array, fun) array.filter(fun)
bfontaine

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

มันใช้งานได้สำหรับฉัน!


4

หากคุณมีฟังก์ชั่นใด ๆ ที่เกี่ยวข้องกับรายการเมื่อคุณสร้างฟังก์ชั่นรอยต่อความสัมพันธ์จะถูกลบด้วย ทางออกของฉัน:

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

พระรามรายการเป็นชื่อรายการ พารามิเตอร์x.doneระบุว่ารายการนั้นจะถูกลบหรือไม่

การอ้างอิงอื่น: อีกตัวอย่างหนึ่ง

หวังว่าจะช่วยคุณ ทักทาย.


2

สำหรับคำตอบที่ยอมรับของ @Joseph Silber ไม่ทำงานเนื่องจาก indexOf ส่งคืน -1 อาจเป็นเพราะ Angular เพิ่มแฮชคีย์ซึ่งแตกต่างกันสำหรับ $ scope.items [0] และรายการของฉัน ฉันพยายามแก้ไขปัญหานี้ด้วยฟังก์ชั่น angular.toJson () แต่มันไม่ทำงาน :(

อ่าฉันรู้สาเหตุ ... ฉันใช้วิธีการสร้างคอลัมน์สองคอลัมน์ในตารางของฉันโดยดู $ scope.items ขออภัย!



1

Angular มีฟังก์ชั่นในตัวที่เรียกว่าarrayRemoveในกรณีของคุณวิธีการสามารถ:

arrayRemove($scope.persons, person)


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.