Ng-click kullanarak bir diziden bir öğeyi veya nesneyi nasıl silebilirim?


261

Düğmeye tıklandığında bir öğeyi kaldırmamı sağlayan bir işlev yazmaya çalışıyorum, ancak işlevle karıştırıldığımı düşünüyorum - kullanıyorum $digestmu?

HTML ve 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'ın özet döngüsüne girmek için kullanıldığından $ digest istemezsiniz (ve ng tıklaması nedeniyle zaten bir özet döngüsünde olursunuz). Bir diziden bir öğeyi kaldırmaya mı çalışıyorsunuz?
Mark Rajcok

@MarkRajcok :) evet thats ne yapmaya çalışıyorum
Jess McKenzie

remove()içinde ng-clickyol bunu hiçbir bağlam vardır var. Nelerin kaldırıldığını ve içinde olup olmadığını ng-repeatveya kaldırılan öğenin nereden geldiğini veya hangi davranışı istediğinizi göstermek için işaretlemede daha fazla ayrıntıya ihtiyacınız varremove()
charlietfl 16:13

@charlietfl ng-tekrar içinde Soruyu güncelledim
Jess McKenzie

Yanıtlar:


552

Öğeyi kaldırmak için diziden kaldırmanız gerekir ve bdayöğeyi biçimlendirme içindeki kaldırma işlevinize iletebilirsiniz . Sonra denetleyicide öğenin dizinine bakın ve diziden kaldırın

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

Sonra denetleyicide:

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

Açısal, bdaysdizideki değişikliği otomatik olarak algılar veng-repeat

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

DÜZENLEME: Sunucu ile canlı güncellemeler yapmak $resourcedizi güncellemelerini yönetmek için oluşturduğunuz bir hizmeti aynı anda kullanırsa sunucuyu günceller


62
$indexListeniz şablonda filtrelenirse doğrudan kullanmak hatalara neden olabilir. Bu bir şablon şey; o ng-click='remove(bday)'zaman kullanmak daha güvenliarr.splice(arr.indexOf(bday),1);
Umur Kontacı

6
Yöntemin içinde 'this' ifadesini kullanabileceğiniz için $ dizinini iletmeniz gerekmez. $ scope.remove = function () {$ scope.bdays.splice (bu. $ dizini, 1); }
matchdav

1
@matthewdavidson this is undefined. Plunker / jsfiddle belki?
Tjorriemorrie

11
.indexOf(item)bulunmazsa -1 döndürürse, dizinin sonunda öğeyi kaldırmazsanız bu öğe kaldırılabilir.
Ben Wilde


54

Bu doğru bir cevap:

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

@ Charlietfl'in cevabında. $indexParamter olarak geçtiğiniz için yanlış olduğunu düşünüyorum ama denetleyicide bunun yerine dileği kullanıyorsunuz. Yanlışsam düzelt :)


işleviniz $ olmadan dizini kabul edebilse de her iki yanıt da eşdeğer gibi görünüyor ve yine de çalışacak.
svarog

bu doğru cevap olmalı. indexOfSADECE IE9 + ise çalışır
levi

17
Tekrarlamanızda bir sipariş veya filtre varsa bu işe yaramaz
Joan-Diego Rodriguez

Eğer $ endeksi ile parça kullandıysanız bu daha iyi çalışacaktır
Ankit Balyan

Eğer orderby sadece XMLilley en okumak aldırma / bir filtre var mı varsa Joan-DiegoRodriguez @ nasıl işe alacağı Cevap
jamesmstone

26

Bir tekrarlamanın içindeysen

bir astar seçeneği kullanabilirsiniz

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

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

$index içindeki dizinin geçerli dizinini göstermek için açısal tarafından kullanılır ng-repeat


1
Sevdim

24

Kullanımı $indextemel durumlarda mükemmel çalışır ve @ charlietfl'in cevabı harika. Ancak bazen,$index yeterli olmaz.

İki farklı tekrarda sunduğunuz tek bir diziniz olduğunu düşünün. Bu tekrarlardan biri, gerçek bir özelliğe sahip nesneler için filtrelenir ve diğeri, bir sahte özellik için filtrelenir. Tek bir orijinal diziden türetilen iki farklı filtrelenmiş dizi sunulmaktadır. (Ya da görselleştirmeye yardımcı oluyorsa: belki de tek bir kişiden oluşan bir diziniz vardır ve bu dizideki kadınlar için bir ng ve aynı dizideki erkekler için başka bir ng tekrar etmek istersiniz .) Hedefiniz: Orijinal dizi, filtrelenmiş dizilerin üyelerinden gelen bilgileri kullanarak.

Filtrelenen dizilerin her birinde, $ index, orijinal dizideki öğenin dizini olmaz. Bu dizin olacak süzülmüş alt-dizide . Böylece, kişinin dizinini orijinal peopledizide söyleyemezsiniz, yalnızca $ dizinini womenveyamen alt diziden . Bunu kullanarak silmeyi deneyin, istediğiniz yerde hariç her yerden öğeler kaybolur. Ne yapalım?

Her nesne için benzersiz bir tanımlayıcı içeren bir veri modeli kullanmakta yeterince şanslıysanız, nesneyi bulmak için $ index yerine splice onu ana dizinin dışında . (Aşağıdaki örneğimi kullanın, ancak bu benzersiz tanımlayıcı ile.) Ama çok şanslı değilseniz?

Açısal, ng yinelenen bir dizideki (ana, orijinal dizide) her öğeyi benzersiz bir özellik ile artırır $$hashKey. Orijinal dizide eşleşme için arama yapabilirsiniz.$$hashKey silmek istediğiniz öğenin bu şekilde ondan kurtulabilirsiniz.

$$hashKeyNg-tekrar için yayınlanmış API'da bulunmayan bir uygulama ayrıntısı olduğunu unutmayın . Bu mülke verilen desteği istedikleri zaman kaldırabilirler. Ama muhtemelen hayır. :-)

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

Şununla ara:

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

DÜZENLEME: $$hashKeyModele özgü özellik adı yerine kullanılan tuşlar gibi bir işlev kullanmak, bu işlevi farklı modellerde ve bağlamlarda yeniden kullanılabilir hale getirme avantajına da sahiptir. Dizi referansınızı ve öğe referansınızı sağlayın ve sadece işe yarayacaktır.


10

Genellikle böyle bir tarzda yazarım:

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


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

Umarım bu yardımcı olur $ scope ve [yourArray] arasında bir nokta (.) Kullanmanız gerekir


"İndex" in (index, 1) anlamı nedir
ShibinRagh

@ShibinRagh Bu deleteCount. Kaldırılacak eski dizi öğelerinin sayısını gösteren bir tam sayı. DeleteCount 0 ise, hiçbir öğe kaldırılmaz. Bu durumda, en az bir yeni öğe belirtmelisiniz. DeleteCount, başlangıçta dizide kalan öğe sayısından büyükse, dizinin sonundaki tüm öğeler silinir. Array.prototype.splice () Belgeler
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

9

Kabul cevap üzerine kurulan bu çalışacaktır ngRepeat, filtersap expections daha iyi ve:

Denetleyici:

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

Görünüm:

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

Denetleyicinizdeki $ scope.vm dosyasına "kaldır" komutu atamadınız, bu nedenle bu kod çalışmaz. Şimdi bunu yaptıysanız ... $ scope.vm = {remove: function () {...}}, o zaman olur.
Justin Russo

4

Denetleyici Olmadan uygulama.

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

Splice () yöntemi, bir diziye / dizisinden öğe ekler / kaldırır.

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

endeksi : Gerekli. Hangi konuma öğe ekleneceğini / kaldırılacağını belirten bir tamsayı, Dizinin sonundaki konumu belirtmek için negatif değerleri kullanın.

howmanyitem (ler) : İsteğe bağlı. Kaldırılacak öğe sayısı. 0 olarak ayarlanırsa, hiçbir öğe kaldırılmaz.

item_1, ..., item_n : İsteğe bağlı. Diziye eklenecek yeni öğeler


1
Bu doğru cevap. Basit JavaScript çağrıları yapmak için neden bir denetleyiciye güvenmelisiniz?
Elle Fie

3

Denetleyicinizde bir yöntem çağırmanız gerektiğini kabul etmiyorum. Herhangi bir gerçek işlevsellik için bir hizmet kullanmanız ve ölçeklenebilirlik ve modülerlik için herhangi bir işlevsellik için yönergeler tanımlamanız ve yönergenize enjekte ettiğiniz hizmete bir çağrı içeren bir tıklama etkinliği atamanız gerekir.

Örneğin, HTML'nizde ...

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

Ardından, bir yönerge oluşturun ...

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

O zaman hizmetinizde ...

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

Kodunuzu böyle düzgün bir şekilde yazdığınızda, kodunuzu yeniden yapılandırmanıza gerek kalmadan gelecekteki değişiklikleri yazmayı çok kolay hale getireceksiniz. Düzgün düzenlenmiştir ve özel yönergeleri kullanarak bağlanarak özel tıklama etkinliklerini doğru bir şekilde yönetirsiniz.

Örneğin, müşteriniz "Hey, şimdi sunucuyu aramasını ve ekmek yapmasını ve ardından bir mod belirlemesi" derse. HTML ve / veya denetleyici yöntem kodlarından herhangi birini eklemek veya değiştirmek zorunda kalmadan kolayca hizmete gidebilirsiniz. Denetleyicide yalnızca bir satırınız varsa, işlevselliği istemcinin istediği daha ağır kaldırmaya genişletmek için bir hizmet kullanmanız gerekir.

Ayrıca, başka bir yerde başka bir 'Sil' düğmesine ihtiyacınız varsa, artık sayfadaki herhangi bir öğeye kolayca atayabileceğiniz bir yönerge niteliğiniz ('ng-remove-birthday') var. Bu artık onu modüler ve tekrar kullanılabilir hale getiriyor. Bu, Angular 2.0'ın AĞIR web bileşenleri paradigmasıyla uğraşırken kullanışlı olacaktır. 2.0'da kontrolör yoktur. :)

Mutlu Gelişme !!!



0

öğenizde kimliğiniz veya belirli bir alanınız varsa, filter () kullanabilirsiniz. Where () gibi davranır.

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

denetleyicide:

$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 

(İşlev aynı denetleyicide olabilir, ancak bir hizmette tutmayı tercih eder)

    function removeInfo(id) {
    let item = bdays.filter(function(item) {
      return bdays.id=== id;
    })[0];
    let index = bdays.indexOf(item);
    data.device.splice(indexOfTabDetails, 1);
  }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.