web-dev-qa-db-ja.com

Ng-clickを使って配列からアイテムやオブジェクトを削除するにはどうすればいいですか?

ボタンがクリックされたときにアイテムを削除できるようにする関数を書き込もうとしていますが、関数と混同されていると思います - $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();
};
248
Jess McKenzie

アイテムを削除するには、それを配列から削除する必要があり、マークアップで削除関数にbdayアイテムを渡すことができます。それからコントローラでitemのインデックスを調べて配列から削除します

<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の更新を行います

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

編集:サーバでライブアップデートを行う場合、サーバのアップデートと同時にアレイのアップデートを管理するために$resourceを使用して作成したサービスを使用する場合

528
charlietfl

これは正しい答えです。

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

@ charlietflの答えに。 $indexをパラメータとして渡しているので間違っていると思いますが、コントローラでは代わりに願い事を使います。間違っていれば訂正してください:)

50
nXqd

ng-repeatの中にいる場合

あなたはワンライナーオプションを使用することができます

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

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

$indexは、ng-repeat内の配列の現在のインデックスを示すためにangleによって使用されます。

24
azerafati

$indexを使うことは基本的な場合には完全にうまくいきます、そして@ charlietflの答えは素晴らしいです。しかし時々、$indexは十分ではありません。

単一の配列があり、それが2つの異なるng-repeatで表示されているとします。これらのng-repeatの1つは真実の性質を持つオブジェクトに対してフィルタリングされ、もう1つは偽の性質に対してフィルタリングされます。単一の元の配列から派生した、2つの異なるフィルター処理された配列が提示されています。 (あるいは、視覚化するのに役立つなら:あなたはたぶん単一の人々の配列を持っていて、そしてあなたはその配列の中の女性のための1つのngリピートと その同じ配列 の中のもう一つを望みます。)あなたの目標:フィルター処理された配列のメンバーからの情報を使用して、元の配列から確実に削除します。

これらのフィルタ処理された配列のそれぞれで、$ indexは元の配列内の項目のインデックスにはなりません。これは フィルタ処理されたサブ配列 のインデックスになります。ですから、元のpeople配列で人のインデックスを見分けることはできません。womenまたはmenサブ配列から得られる$インデックスだけがわかります。それを使って削除しようとすると、あなたが欲しいところを除いてどこからでもアイテムが消えてしまうでしょう。何をすべきか?

それぞれのオブジェクトに一意の識別子を含むデータモデルを使用しているのであれば、そのオブジェクトを検索してメイン配列からspliceするために、$ indexの代わりにそれを使用します。 (下記の私の例を使いなさい、しかしそのユニークな識別子を使って)。

Angularは実際には、$$hashKeyという固有のプロパティを使用して、(メインの元の配列の)ng繰り返し配列の各項目を補強します。あなたが削除したいアイテムの$$hashKeyにマッチするためにオリジナルの配列を検索し、そのようにしてそれを取り除くことができます。

$$hashKeyは実装の詳細であり、ng-repeatの公開APIには含まれていません。彼らはいつでもその資産のサポートを削除することができます。しかしそうではないでしょう。 :-)

$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をキーとするこのような関数を使用することは、この関数が異なるモデルやコンテキストにまたがって再利用可能になるという大きな追加の利点も持っています。それをあなたの配列参照とあなたのアイテム参照で提供すれば、それはちょうどうまくいくはずです。

22
XML

私は通常こんな風に書いています:

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


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

これがあなたが$ scopeと[yourArray]の間にドット(。)を使わなければならないのに役立つことを願っています

受け入れられた答えを基にして、これはngRepeatfilterで動作し、期待をより良く処理します。

コントローラー:

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

表示:

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

コントローラなしの実装.

<!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()メソッドは配列にアイテムを追加したり、配列からアイテムを削除したりします。

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

index :必須。項目を追加または削除する位置を指定する整数。配列の末尾からの位置を指定するには負の値を使用します。

howmanyitem(s) :オプション。削除するアイテムの数0に設定すると、アイテムは削除されません。

item_1、...、item_n :オプション。配列に追加される新しい項目

4
Deepu Reghunath

私はあなたがあなたのコントローラ上のメソッドを呼び出すべきであることに同意しません。実際の機能にはサービスを使用し、スケーラビリティとモジュール性の機能にはディレクティブを定義し、ディレクティブに挿入したサービスへの呼び出しを含むclickイベントを割り当てる必要があります。

だから、たとえば、あなたの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やコントローラのメソッドコードを追加または変更しなくても、サービス自体に簡単にアクセスできます。コントローラに1行しかない場合は、最終的にサービスを使用する必要があります。クライアントが要求しているより重いものに機能を拡張するためです。

また、別の場所に別の[削除]ボタンが必要な場合は、ページ上の任意の要素に簡単に割り当てることができるディレクティブ属性( 'ng-remove-birthday')があります。これにより、モジュール化されて再利用可能になりました。これは、Angular 2.0のHEAVY Webコンポーネントパラダイムを扱うときに役立ちます。 2.0にはISコントローラがありません。 :)

幸せな開発中!

3
Justin Russo

これはもう一つの答えです。助けになれば幸いです。

<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

1

あなたがあなたの商品にIDまたは特定のフィールドを持っているなら、あなたはfilter()を使うことができます。 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
                });
}
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);
  }
0
Utkarsh Joshi