Bagaimana cara menghapus item atau objek dari array menggunakan ng-klik?

261

Saya mencoba untuk menulis fungsi yang memungkinkan saya untuk menghapus item ketika tombol diklik tetapi saya pikir saya menjadi bingung dengan fungsinya - apakah saya menggunakan $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();
};
Jess McKenzie
sumber
2
Anda tidak ingin $ digest, karena itu digunakan untuk memasukkan loop digest Angular (dan Anda sudah berada dalam loop digest karena klik-ng). Apakah Anda mencoba menghapus item dari array?
Mark Rajcok
@ MarkRajcok :) ya itulah yang saya coba lakukan
Jess McKenzie
remove()di ng-clickjalan Anda tidak memiliki konteks. Perlu detail lebih lanjut dalam markup untuk menunjukkan apa yang dihapus dan jika ada di dalam ng-repeat, atau dari mana barang yang dihapus berasal, atau perilaku apa yang Anda inginkanremove()
charlietfl
@charlietfl itu masih ng-repeat Saya telah memperbarui pertanyaan
Jess McKenzie
Inilah artikel saya yang menjelaskan cara menghapus catatan dengan ng-repeat codepedia.info/angularjs-delete-table-row-tr-on-click
Satinder singh

Jawaban:

552

Untuk menghapus item, Anda harus menghapusnya dari array dan dapat meneruskan bdayitem ke fungsi hapus Anda di markup. Kemudian di controller cari indeks item dan hapus dari array

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

Kemudian di controller:

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

Angular akan secara otomatis mendeteksi perubahan pada bdaysarray dan melakukan pembaruanng-repeat

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

EDIT: Jika melakukan pembaruan langsung dengan server akan menggunakan layanan yang Anda buat menggunakan $resourceuntuk mengelola pembaruan array pada saat yang sama pembaruan server

charlietfl
sumber
62
Menggunakan $indexsecara langsung dapat menghasilkan bug jika daftar Anda difilter pada templat. Ini hal template; lebih aman untuk digunakan ng-click='remove(bday)'kemudianarr.splice(arr.indexOf(bday),1);
Umur Kontacı
6
Anda tidak perlu melewati $ index karena Anda dapat menggunakan 'ini' di dalam metode. $ scope.remove = function () {$ scope.bdays.splice (this. $ index, 1); }
matchdav
1
@matthewdavidson this is undefined. Plunker / jsfiddle mungkin?
Tjorriemorrie
11
.indexOf(item)akan mengembalikan -1 jika tidak ditemukan, ini dapat mengakibatkan penghapusan item di akhir array jika Anda tidak memeriksanya.
Ben Wilde
1
@ShibinRagh membaca dokumen untuk Array.prototype.splice ()
charlietfl
54

Ini jawaban yang benar:

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

Dalam jawaban @ charlietfl. Saya pikir itu salah karena Anda lulus $indexsebagai paramter tetapi Anda menggunakan keinginan sebagai gantinya di controller. Perbaiki saya jika saya salah :)

Dzung Nguyen
sumber
sepertinya kedua jawaban itu setara, walaupun fungsi Anda dapat menerima indeks tanpa $ dan tetap berfungsi.
svarog
ini seharusnya jawaban yang benar. indexOfHANYA berfungsi jika IE9 +
levi
17
Ini tidak akan berfungsi jika Anda memiliki orderBy atau filter di ng-repeat Anda
Joan-Diego Rodriguez
Ini akan bekerja lebih baik, jika Anda telah menggunakan trek dengan $ index
Ankit Balyan
@ Joan-DiegoRodriguez Bagaimana Anda membuatnya bekerja jika Anda memiliki filter / orderby Sudahlah, baca saja Jawaban
XMLilley
26

Jika Anda berada di dalam ng-repeat

Anda bisa menggunakan opsi satu liner

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

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

$index digunakan oleh angular untuk menunjukkan indeks array saat ini ng-repeat

azerafati
sumber
1
Saya suka dan menggunakan liner yang satu ini
etoricky
24

Menggunakan $indexberfungsi dengan sangat baik dalam kasus dasar, dan jawaban @ charlietfl sangat bagus. Tetapi terkadang, $indexitu tidak cukup.

Bayangkan Anda memiliki satu array, yang Anda presentasikan dalam dua ng-repeat yang berbeda. Salah satu dari mereka ng-repeat difilter untuk objek yang memiliki properti kebenaran, dan yang lainnya difilter untuk properti palsu. Dua array yang difilter sedang disajikan, yang berasal dari satu array asli. (Atau, jika itu membantu untuk memvisualisasikan: mungkin Anda memiliki satu array orang, dan Anda ingin satu ng-repeat untuk wanita dalam array itu, dan yang lain untuk pria dalam array yang sama .) Tujuan Anda: hapus andal dari array asli, menggunakan informasi dari anggota array yang difilter.

Di setiap array yang difilter, $ index tidak akan menjadi indeks item dalam array asli. Ini akan menjadi indeks dalam sub-array yang difilter . Jadi, Anda tidak akan dapat memberi tahu indeks orang tersebut dalam peoplearray asli , Anda hanya akan tahu $ index dari womenatau mensub-array. Cobalah untuk menghapus menggunakan itu, dan Anda akan memiliki item menghilang dari mana-mana kecuali di mana Anda inginkan. Apa yang harus dilakukan?

Jika Anda cukup beruntung menggunakan model data termasuk pengidentifikasi unik untuk setiap objek, kemudian gunakan itu daripada $ indeks, untuk menemukan objek dan splicekeluar dari array utama. (Gunakan contoh saya di bawah ini, tetapi dengan pengenal unik itu.) Tetapi jika Anda tidak seberuntung itu?

Angular sebenarnya menambah setiap item dalam array yang diulang-ulang (dalam array asli dan asli) dengan properti unik yang disebut $$hashKey. Anda dapat mencari array asli untuk menemukan kecocokan pada $$hashKeyitem yang ingin Anda hapus, dan singkirkan seperti itu.

Perhatikan bahwa $$hashKeyini adalah detail implementasi, tidak termasuk dalam API yang diterbitkan untuk ng-repeat. Mereka dapat menghapus dukungan untuk properti itu kapan saja. Tapi mungkin juga tidak. :-)

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

Diminta dengan:

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

EDIT: Menggunakan fungsi seperti ini, yang menekan pada $$hashKeyalih - alih nama properti khusus model, juga memiliki keuntungan tambahan yang signifikan membuat fungsi ini dapat digunakan kembali di berbagai model dan konteks yang berbeda. Berikan itu dengan referensi array Anda, dan referensi item Anda, dan itu hanya akan berfungsi.

XML
sumber
10

Saya biasanya menulis dengan gaya seperti itu:

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


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

Semoga ini bisa membantu Anda harus menggunakan titik (.) Antara $ scope dan [yourArray]

Sviatoslav Novosiadlyj
sumber
Apa arti dari "1" di (indeks, 1)
ShibinRagh
@ ShibinRagh Ini adalah deleteCount. Integer yang menunjukkan jumlah elemen array lama untuk dihapus. Jika deleteCount adalah 0, tidak ada elemen yang dihapus. Dalam hal ini, Anda harus menentukan setidaknya satu elemen baru. Jika deleteCount lebih besar dari jumlah elemen yang tersisa dalam array mulai dari awal, maka semua elemen hingga akhir array akan dihapus. Array.prototype.splice () Dokumentasi
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
9

Membangun jawaban yang diterima, ini akan bekerja dengan ngRepeat, filterdan menangani ekspektasi dengan lebih baik:

Pengendali:

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

Melihat:

ng-click="vm.remove(item,$scope.bdays)"
Joan-Diego Rodriguez
sumber
Anda tidak menetapkan, "hapus" ke $ scope.vm di controller Anda, jadi kode ini tidak akan berfungsi. Sekarang jika Anda melakukan ini ... $ scope.vm = {remove: function () {...}}, maka itu akan terjadi.
Justin Russo
4

implementasi Tanpa Pengendali.

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

Metode splice () menambah / menghapus item ke / dari array.

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

indeks : Diperlukan. Integer yang menentukan pada posisi apa untuk menambah / menghapus item, Gunakan nilai negatif untuk menentukan posisi dari akhir array.

howmanyitem (s) : Opsional. Jumlah item yang akan dihapus. Jika diatur ke 0, tidak ada item yang akan dihapus.

item_1, ..., item_n : Opsional. Item baru yang akan ditambahkan ke array

Deepu Reghunath
sumber
1
Ini adalah jawaban yang benar. Mengapa mengandalkan pengontrol untuk melakukan panggilan JavaScript sederhana?
Elle Fie
3

Saya tidak setuju bahwa Anda harus memanggil metode pada controller Anda. Anda harus menggunakan layanan untuk fungsionalitas aktual apa pun, dan Anda harus menentukan arahan untuk fungsionalitas apa pun untuk skalabilitas dan modularitas, serta menetapkan acara klik yang berisi panggilan ke layanan yang Anda masukkan ke dalam arahan Anda.

Jadi, misalnya, pada HTML Anda ...

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

Lalu, buat arahan ...

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

Kemudian dalam layanan Anda ...

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

Ketika Anda menulis kode dengan benar seperti ini, Anda akan membuatnya sangat mudah untuk menulis perubahan di masa depan tanpa harus merestrukturisasi kode Anda. Ini diatur dengan benar, dan Anda menangani acara klik khusus dengan benar dengan mengikat menggunakan arahan khusus.

Misalnya, jika klien Anda berkata, "hei, sekarang mari kita membuatnya memanggil server dan membuat roti, dan kemudian memunculkan modal." Anda akan dapat dengan mudah pergi ke layanan itu sendiri tanpa harus menambahkan atau mengubah kode metode HTML, dan / atau controller. Jika Anda hanya memiliki satu baris pada controller, Anda akhirnya harus menggunakan layanan, untuk memperluas fungsionalitas ke pengangkatan yang lebih berat yang diminta klien.

Juga, jika Anda membutuhkan tombol 'Hapus' lain di tempat lain, Anda sekarang memiliki atribut direktif ('ng-remove-birthday') Anda dapat dengan mudah menetapkan elemen apa pun pada halaman. Ini sekarang membuatnya modular dan dapat digunakan kembali. Ini akan berguna ketika berhadapan dengan paradigma komponen web HEAVY dari Angular 2.0. Tidak ada controller di 2.0. :)

Selamat Berkembang !!!

Justin Russo
sumber
0

jika Anda memiliki ID atau bidang spesifik apa pun di item Anda, Anda dapat menggunakan filter (). aktingnya seperti Where ().

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

dalam controller:

$scope.remove = function(item) { 
  $scope.bdays = $scope.bdays.filter(function (element) {
                    return element.ID!=item.ID
                });
}
Sayyid Reza Dadrezaei
sumber
0
Pass the id that you want to remove from the array to the given function 

dari controller (Fungsi bisa di controller yang sama tetapi lebih suka menyimpannya dalam layanan)

    function removeInfo(id) {
    let item = bdays.filter(function(item) {
      return bdays.id=== id;
    })[0];
    let index = bdays.indexOf(item);
    data.device.splice(indexOfTabDetails, 1);
  }
Utkarsh Joshi
sumber