ฉันจะลบรายการหรือวัตถุออกจากอาร์เรย์โดยใช้ ng-click ได้อย่างไร


261

ฉันพยายามเขียนฟังก์ชั่นที่ช่วยให้ฉันสามารถลบรายการเมื่อคลิกปุ่ม แต่ฉันคิดว่าฉันสับสนกับฟังก์ชั่น - ฉันจะใช้$digestหรือไม่

HTML & app.js:

<ul ng-repeat="bday in bdays">
  <li>
    <span ng-hide="editing" ng-click="editing = true">{{bday.name}} | {{bday.date}}</span>
    <form ng-show="editing" ng-submit="editing = false">
      <label>Name:</label>
      <input type="text" ng-model="bday.name" placeholder="Name" ng-required/>
      <label>Date:</label>
      <input type="date" ng-model="bday.date" placeholder="Date" ng-required/>
      <br/>
      <button class="btn" type="submit">Save</button>
      <a class="btn" ng-click="remove()">Delete</a>
    </form>
  </li>
</ul>

$scope.remove = function(){
  $scope.newBirthday = $scope.$digest();
};

2
คุณไม่ต้องการให้ $ แยกย่อยเนื่องจากมันถูกใช้เพื่อเข้าสู่ห่วงย่อยของ Angular (และคุณอยู่ในห่วงย่อยแล้วเพราะ ng-click) คุณพยายามที่จะลบรายการออกจากอาร์เรย์?
Mark Rajcok

@ MarkRajcok :) ใช่นั่นคือสิ่งที่ฉันกำลังพยายามทำอยู่
Jess McKenzie

remove()ในng-clickแบบที่คุณมีมันไม่มีบริบท ต้องการรายละเอียดเพิ่มเติมในมาร์กอัปเพื่อแสดงสิ่งที่ถูกลบออกและถ้ามันอยู่ภายในng-repeatหรือที่ถูกลบรายการมาจากหรือพฤติกรรมที่คุณต้องการจากremove()
charlietfl

@charlietfl มันอยู่ภายใน ng-repeat ฉันได้อัปเดตคำถาม
Jess McKenzie

นี่คือ 1 บทความของฉันซึ่งอธิบายวิธีการลบบันทึกด้วย ng-repeat codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

คำตอบ:


551

ในการลบรายการคุณต้องลบออกจากอาร์เรย์และสามารถส่งbdayรายการไปยังฟังก์ชันลบของคุณในมาร์กอัป จากนั้นในตัวควบคุมค้นหาดัชนีของรายการและลบออกจากอาร์เรย์

<a class="btn" ng-click="remove(item)">Delete</a>

จากนั้นในตัวควบคุม:

$scope.remove = function(item) { 
  var index = $scope.bdays.indexOf(item);
  $scope.bdays.splice(index, 1);     
}

Angular จะตรวจจับการเปลี่ยนแปลงในbdaysอาร์เรย์โดยอัตโนมัติและทำการอัปเดตng-repeat

DEMO: http://plnkr.co/edit/ZdShIA?p=preview

แก้ไข: หากทำการอัปเดตสดกับเซิร์ฟเวอร์จะใช้บริการที่คุณสร้างโดยใช้ $resourceเพื่อจัดการการอัปเดตอาร์เรย์ในเวลาเดียวกันเป็นการอัปเดตเซิร์ฟเวอร์


62
การใช้$indexโดยตรงสามารถสร้างข้อบกพร่องหากรายการของคุณถูกกรองในแม่แบบ มันเป็นสิ่งที่แม่แบบ; มันเป็นสิ่งที่ปลอดภัยในการใช้งานng-click='remove(bday)'แล้วarr.splice(arr.indexOf(bday),1);
Umur Kontacı

6
คุณไม่จำเป็นต้องผ่านการ $ index เพราะคุณสามารถใช้ 'this' ภายในเมธอด $ scope.remove = function () {$ scope.bdays.splice (นี่. $ index, 1); }
matchdav

1
this is undefined@matthewdavidson Plunker / jsfiddle อาจจะ?
Tjorriemorrie

11
.indexOf(item)จะส่งคืน -1 หากไม่พบสิ่งนี้อาจส่งผลให้เกิดการลบรายการในตอนท้ายของอาร์เรย์ถ้าคุณไม่ตรวจสอบ
Ben Wilde

1
@ShibinRagh อ่านเอกสารสำหรับArray.prototype.splice ()
charlietfl

54

นี่คือคำตอบที่ถูกต้อง:

<a class="btn" ng-click="remove($index)">Delete</a>
$scope.remove=function($index){ 
  $scope.bdays.splice($index,1);     
}

ในคำตอบของ @ charlietfl ฉันคิดว่ามันผิดเพราะคุณผ่าน$indexเป็นพารามิเตอร์ แต่คุณใช้ความปรารถนาแทนตัวควบคุม ช่วยแก้ให้ด้วยนะถ้าฉันผิด :)


ดูเหมือนว่าคำตอบทั้งสองนั้นมีค่าเท่ากันถึงแม้ว่าฟังก์ชั่นของคุณสามารถรับดัชนีโดยไม่ต้องใช้ $ และมันจะยังทำงานได้
svarog

นี่ควรเป็นคำตอบที่ถูกต้อง indexOfใช้งานได้เฉพาะถ้าเป็น IE9 +
levi

17
สิ่งนี้จะไม่ทำงานหากคุณมีคำสั่งซื้อโดยใช้ตัวกรองหรือ ng-repeat ในตัวคุณเอง
Joan-Diego Rodriguez

สิ่งนี้จะทำงานได้ดีขึ้นหากคุณใช้การติดตามด้วย $ index
Ankit Balyan

@ Joan-DiegoRodriguez คุณจะให้มันทำงานอย่างไรถ้าคุณมีตัวกรอง / คำสั่งโดยไม่ต้องสนใจแค่อ่านคำตอบ
XMLilley

26

ในกรณีที่คุณอยู่ใน ng-repeat

คุณสามารถใช้หนึ่งตัวเลือกซับ

    <div ng-repeat="key in keywords"> 
        <button ng-click="keywords.splice($index, 1)">

            {{key.name}}
        </button>
    </div>

$index ถูกใช้โดยเชิงมุมเพื่อแสดงดัชนีปัจจุบันของอาร์เรย์ภายใน ng-repeat


1
ฉันชอบและใช้สายการบินเดียวนี้
etoricky

24

การใช้$indexงานได้ดีอย่างสมบูรณ์ในกรณีพื้นฐานและคำตอบของ @ charlietfl นั้นยอดเยี่ยม แต่บางครั้ง$indexก็ไม่เพียงพอ

ลองนึกภาพคุณมีอาเรย์เดี่ยวซึ่งคุณกำลังนำเสนอในซ้ำสองอันที่ต่างกัน หนึ่งใน ng-repeat นั้นถูกกรองสำหรับวัตถุที่มีคุณสมบัติที่เป็นความจริงและอีกอันหนึ่งถูกกรองสำหรับคุณสมบัติที่เป็นเท็จ มีการนำเสนออาร์เรย์ที่กรองที่แตกต่างกันสองแบบซึ่งมาจากอาเรย์ดั้งเดิมหนึ่งชุด (หรือถ้าช่วยให้มองเห็นได้: บางทีคุณอาจมีคนจำนวนหนึ่งและคุณต้องการผู้หญิงซ้ำในชุดนั้นและอีกชุดสำหรับผู้ชายในชุดเดียวกัน ) เป้าหมายของคุณ: ลบได้อย่างน่าเชื่อถือ อาร์เรย์ดั้งเดิมโดยใช้ข้อมูลจากสมาชิกของอาร์เรย์ที่ถูกกรอง

ในแต่ละอาร์เรย์ที่ถูกกรอง $ index จะไม่เป็นดัชนีของรายการภายในอาร์เรย์เดิม มันจะเป็นดัชนีในการกรองย่อยอาร์เรย์ ดังนั้นคุณจะไม่สามารถบอกดัชนีของบุคคลนั้นในpeopleอาเรย์เดิมได้คุณจะรู้เพียงแค่ $ $ จากอาเรย์womenหรือmenอาเรย์ย่อย พยายามที่จะลบโดยใช้ที่และคุณจะมีรายการหายไปจากทุกที่ยกเว้นที่คุณต้องการ จะทำอย่างไร?

หากคุณโชคดีพอที่จะใช้แบบจำลองข้อมูลรวมถึงตัวระบุที่ไม่ซ้ำกันสำหรับแต่ละวัตถุให้ใช้สิ่งนั้นแทน $ index เพื่อค้นหาวัตถุและspliceออกจากอาร์เรย์หลัก (ใช้ตัวอย่างของฉันด้านล่าง แต่ใช้ตัวระบุที่ไม่ซ้ำกัน) แต่ถ้าคุณไม่โชคดีล่ะ

เชิงมุมจริง augments แต่ละรายการในอาร์เรย์ NG-ซ้ำ (ในหลักอาร์เรย์เดิม) $$hashKeyที่มีคุณสมบัติเฉพาะที่เรียกว่า คุณสามารถค้นหาอาเรย์ดั้งเดิมเพื่อหาคู่ที่ตรงกับ$$hashKeyของรายการที่คุณต้องการลบและกำจัดอย่างนั้น

โปรดทราบว่า$$hashKeyนี่คือรายละเอียดการใช้งานซึ่งไม่รวมอยู่ใน API ที่เผยแพร่สำหรับ ng-repeat พวกเขาสามารถลบการสนับสนุนสำหรับคุณสมบัตินั้นได้ตลอดเวลา แต่อาจจะไม่ :-)

$scope.deleteFilteredItem = function(hashKey, sourceArray){
  angular.forEach(sourceArray, function(obj, index){
    // sourceArray is a reference to the original array passed to ng-repeat, 
    // rather than the filtered version. 
    // 1. compare the target object's hashKey to the current member of the iterable:
    if (obj.$$hashKey === hashKey) {
      // remove the matching item from the array
      sourceArray.splice(index, 1);
      // and exit the loop right away
      return;
    };
  });
}

เรียกใช้ด้วย:

ng-click="deleteFilteredItem(item.$$hashKey, refToSourceArray)"

แก้ไข: การใช้ฟังก์ชั่นเช่นนี้ซึ่งปุ่มบน$$hashKeyแทนชื่อคุณสมบัติเฉพาะรุ่นยังมีข้อได้เปรียบที่เพิ่มขึ้นอย่างมากในการทำให้ฟังก์ชั่นนี้สามารถใช้ซ้ำได้ในรุ่นและบริบทที่แตกต่างกัน ให้มันมีการอ้างอิงอาร์เรย์ของคุณและการอ้างอิงรายการของคุณและมันก็ควรจะทำงาน


10

ฉันมักจะเขียนในสไตล์เช่นนี้:

<a class="btn" ng-click="remove($index)">Delete</a>


$scope.remove = function(index){
  $scope.[yourArray].splice(index, 1)
};

หวังว่าสิ่งนี้จะช่วยให้คุณใช้จุด (.) ระหว่าง $ scope และ [yourArray]


ความหมายของ "1" ใน (ดัชนี, 1)
อะไร

@ShibinRagh deleteCountมันของ จำนวนเต็มที่ระบุจำนวนองค์ประกอบอาร์เรย์เก่าที่จะลบ หาก deleteCount เป็น 0 จะไม่มีการลบองค์ประกอบใด ๆ ในกรณีนี้คุณควรระบุองค์ประกอบใหม่อย่างน้อยหนึ่งองค์ประกอบ หาก deleteCount มากกว่าจำนวนขององค์ประกอบที่เหลือในอาร์เรย์เริ่มต้นที่เริ่มต้นแล้วองค์ประกอบทั้งหมดที่ผ่านมาในตอนท้ายของอาร์เรย์จะถูกลบ Array.prototype.splice () เอกสารประกอบ
ʙᴀᴋᴇʀʙᴀᴋᴇʀ

9

การสร้างคำตอบที่ยอมรับจะช่วยngRepeatได้filterและจัดการกับความคาดหวังได้ดีกว่า:

ควบคุม:

vm.remove = function(item, array) {
  var index = array.indexOf(item);
  if(index>=0)
    array.splice(index, 1);
}

ดู:

ng-click="vm.remove(item,$scope.bdays)"

คุณไม่ได้กำหนด "ลบ" ให้กับ $ scope.vm ในคอนโทรลเลอร์ของคุณดังนั้นโค้ดนี้จะไม่ทำงาน ทีนี้ถ้าคุณทำสิ่งนี้ ... $ scope.vm = {remove: function () {... }} มันจะเป็นเช่นนั้น
Justin Russo

4

การดำเนินการโดยไม่มีตัวควบคุม

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>

<script>
  var app = angular.module("myShoppingList", []); 
</script>

<div ng-app="myShoppingList"  ng-init="products = ['Milk','Bread','Cheese']">
  <ul>
    <li ng-repeat="x in products track by $index">{{x}}
      <span ng-click="products.splice($index,1)">×</span>
    </li>
  </ul>
  <input ng-model="addItem">
  <button ng-click="products.push(addItem)">Add</button>
</div>

<p>Click the little x to remove an item from the shopping list.</p>

</body>
</html>

วิธีการประกบกัน () วิธีการเพิ่ม / ลบรายการไปยัง / จากอาร์เรย์

array.splice(index, howmanyitem(s), item_1, ....., item_n)

ดัชนี : จำเป็น จำนวนเต็มที่ระบุตำแหน่งที่จะเพิ่ม / ลบรายการใช้ค่าลบเพื่อระบุตำแหน่งจากจุดสิ้นสุดของอาร์เรย์

howmanyitem (s) : ไม่จำเป็น จำนวนรายการที่จะลบ หากตั้งค่าเป็น 0 จะไม่มีการลบรายการใด ๆ

item_1, ... , item_n : ไม่บังคับ รายการใหม่ที่จะเพิ่มลงในอาร์เรย์


1
นี่คือคำตอบที่ถูกต้อง เหตุใดจึงต้องอาศัยคอนโทรลเลอร์เพื่อทำการเรียก JavaScript อย่างง่าย
Elle Fie

3

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

ตัวอย่างเช่นบน HTML ของคุณ ...

<a class="btn" ng-remove-birthday="$index">Delete</a>

จากนั้นสร้างคำสั่ง ...

angular.module('myApp').directive('ngRemoveBirthday', ['myService', function(myService){
    return function(scope, element, attrs){
        angular.element(element.bind('click', function(){
            myService.removeBirthday(scope.$eval(attrs.ngRemoveBirthday), scope);  
        };       
    };
}])

จากนั้นในบริการของคุณ ...

angular.module('myApp').factory('myService', [function(){
    return {
        removeBirthday: function(birthdayIndex, scope){
            scope.bdays.splice(birthdayIndex);
            scope.$apply();
        }
    };
}]);

เมื่อคุณเขียนรหัสของคุณอย่างถูกต้องคุณจะทำให้ง่ายต่อการเขียนการเปลี่ยนแปลงในอนาคตโดยไม่ต้องปรับโครงสร้างรหัสของคุณ มีการจัดระเบียบอย่างถูกต้องและคุณจัดการกิจกรรมการคลิกที่กำหนดเองได้อย่างถูกต้องโดยผูกกับคำสั่งที่กำหนดเอง

ตัวอย่างเช่นหากลูกค้าของคุณบอกว่า "เฮ้ตอนนี้ให้โทรหาเซิร์ฟเวอร์แล้วทำขนมปังแล้วป๊อปอัปโมดอล" คุณจะสามารถไปที่บริการได้อย่างง่ายดายโดยไม่ต้องเพิ่มหรือเปลี่ยนรหัส HTML และ / หรือตัวควบคุมใด ๆ หากคุณมีเพียงหนึ่งบรรทัดบนคอนโทรลเลอร์คุณจะต้องใช้บริการในที่สุดเพื่อขยายการทำงานไปสู่การยกที่หนักกว่าที่ไคลเอนต์ร้องขอ

นอกจากนี้หากคุณต้องการปุ่ม 'ลบ' ปุ่มอื่นที่อื่นตอนนี้คุณมีแอตทริบิวต์ directive ('ng-remove-birthday') คุณสามารถกำหนดองค์ประกอบใด ๆ ในหน้าได้อย่างง่ายดาย ตอนนี้ทำให้เป็นแบบแยกส่วนและสามารถใช้ซ้ำได้ สิ่งนี้จะมีประโยชน์เมื่อต้องรับมือกับกระบวนทัศน์องค์ประกอบของเว็บของ Angular 2.0 ไม่มีคอนโทรลเลอร์ใน 2.0 :)

การพัฒนามีความสุข !!!


1

นี่คือคำตอบอื่น ฉันหวังว่ามันจะช่วย

<a class="btn" ng-click="delete(item)">Delete</a>

$scope.delete(item){
 var index = this.list.indexOf(item);
                this.list.splice(index, 1);   
}

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, ...)

แหล่งข้อมูลเต็มอยู่ที่นี่
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice


0

หากคุณมี ID หรือฟิลด์เฉพาะในรายการของคุณคุณสามารถใช้ตัวกรอง () มันทำหน้าที่เหมือน Where ()

<a class="btn" ng-click="remove(item)">Delete</a>

ในตัวควบคุม:

$scope.remove = function(item) { 
  $scope.bdays = $scope.bdays.filter(function (element) {
                    return element.ID!=item.ID
                });
}

0
Pass the id that you want to remove from the array to the given function 

จากคอนโทรลเลอร์ (ฟังก์ชันสามารถอยู่ในคอนโทรลเลอร์เดียวกัน แต่ต้องการเก็บไว้ในบริการ)

    function removeInfo(id) {
    let item = bdays.filter(function(item) {
      return bdays.id=== id;
    })[0];
    let index = bdays.indexOf(item);
    data.device.splice(indexOfTabDetails, 1);
  }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.