0

I have a row in a modal that I want to be able to delete. New ones can also be added.

I have a trimmed down template as follows:

<div class="filter-row" delete-filter>
    <div class="form-group>
        <div class="delete-filter" ng-click="deleteFilter()"><i class="fa fa-trash"></i></div>
    </div>
</div>

And a directive as follows:

.directive('deleteFilter', function() {
    return {
        restrict: 'A',
        link: function(scope, element) {

            // Scope function to delete a filter row from the DOM
            scope.deleteFilter = function() {
                console.log("Deleting");
                // Remove the directive element
                element.remove();
            };
        }
    };
});

This seems to work well to delete a single filter row. But if a new row is added from this template while a row already exists, I can only delete one of the rows. If I add many rows and want to delete, I can still only delete a single row.

To note: the console log within the function will fire every time a delete row is clicked, whether the row is removed or not.

Any help would be appreciated. I think I am missing something but I can't figure out what.

Edit:

A new filter is added with this function from the controller:

// Function to add a new filter row in the filter modal window
self.addFilterRow = function() {
    var newFilterRow = $compile("<filter-row></filter-row>")($scope);
    $("#filterForm").append(newFilterRow);
};

Here is a Plunkr that may better describe the issue I'm having:

https://plnkr.co/edit/H5fvWmDLmOcnADlxELOo?p=preview

Dan Hodson
  • 309
  • 4
  • 18
  • what is it exactly you want.. i am not able to understand the question – NiRUS Apr 08 '16 at 12:30
  • Is `ng-repeat` involved in your template? – georgeawg Apr 08 '16 at 12:39
  • @georgeawg No this isn't repeated, it's a compiled template – Dan Hodson Apr 08 '16 at 12:40
  • can you post your template? – Hoyen Apr 08 '16 at 13:33
  • Thanks @Hoyen, please see the Plunkr link in the edit above or here: https://plnkr.co/edit/H5fvWmDLmOcnADlxELOo?p=preview – Dan Hodson Apr 08 '16 at 15:15
  • I posted a solution to your problem below. But your implementation is probably not the best practice using angular. Typically you would have a Array of rows, where is row would be a object/model of each row. When you add a row you create a new instance of the row and add it to the array. When you delete one, you would remove that row object from the array. And in the template you would loop through the array with the filter-row directive. – Hoyen Apr 08 '16 at 16:19

4 Answers4

0

If I've understood your question, inherited scope should solve this for you. Add scope: true to the directive, for example:

.directive('deleteFilter', function() {
    return {
        restrict: 'A',
        scope: true,
        link: function(scope, element) {

            // Scope function to delete a filter row from the DOM
            scope.deleteFilter = function() {
                console.log("Deleting");
                // Remove the directive element
                element.remove();
            };
        }
    }; });
carlcheel
  • 621
  • 6
  • 11
  • Thanks @Carlos13, apologies for the poor explanation. This answer prevents any rows being deleted at all. Basically I can add a row with a separate directive calling the template above. However when I want to delete a row using the directive above, I can only ever delete 1 row, even though the console log is always called. Make sense? Thanks again. – Dan Hodson Apr 08 '16 at 12:37
  • I've changed the answer to use inherited scope. Does that give you the desired result? If not, let me know and I'll generate a Plunker for you. – carlcheel Apr 08 '16 at 13:26
  • Thanks @Carlos13 I have added the `scope: true,` but this still only removes a single row, despite how many rows are available to delete. – Dan Hodson Apr 08 '16 at 14:52
  • please see this plunkr which better illustrates the issue https://plnkr.co/edit/H5fvWmDLmOcnADlxELOo?p=preview – Dan Hodson Apr 08 '16 at 15:27
0
    <h3>Repeat stuff:</h3>
<div ng-app='app' ng-controller="MyCtrl">
  <ul>
    <li ng-repeat="(country,goals) in items">{{country}}: {{goals}}
      <div class="filter-row" delete-filter>
        <div class="form-group>
        <div class=" delete-filter " ng-click="deleteFilter() "><input type='button' value='delete'></div>
    </div>
</div>
        </li>
    </ul>
</div>

and the js code is

var items = {
  "India": "2",
  "England": "2",
  "Brazil": "3",
  "UK": "1",
  "USA": "3",
  "Syria": "2"
};

var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
  $scope.items = items;
});

app.directive('deleteFilter', function() {
  return {
    restrict: 'A',
    link: function(scope, element) {

      // Scope function to delete a filter row from the DOM
      scope.deleteFilter = function() {
        console.log("Deleting");
        // Remove the directive element
        element.remove();
      };
    }
  };
});

please find the working fiddle to you problem :

http://jsfiddle.net/RkykR/2326/

hope it works for you also.. :)

Ankur Soni
  • 746
  • 6
  • 17
  • Thanks @Ankur Soni, please see this plunkr which better illustrates the issue https://plnkr.co/edit/H5fvWmDLmOcnADlxELOo?p=preview – Dan Hodson Apr 08 '16 at 15:27
0

Use inherited scope.

.directive('deleteFilter', function() {
    return {
        restrict: 'A',
        //Use inherited scope
        scope: true,
        link: function(scope, element) {

            // Scope function to delete a filter row from the DOM
            scope.deleteFilter = function() {
                console.log("Deleting");
                // Remove the directive element
                element.remove();
            };
        }
    }; 
});

With that, the ng-click="deleteFilter()" will be invoked on the scope created by the deleteFilter directive.


UPDATE

Also remove replace: true in the filterRow directive.

app.directive('filterRow', function() {
        return {
            scope: false,
            //REMOVE this 
            //replace: true,
            restrict: 'E',
            templateUrl: 'filter-row.html',
        };
});

With replace: true on a sibling directive, the inherited scope on the deleteFilter directive was getting removed.

replace:true is Deprecated1

From the Docs:

replace ([DEPRECATED!], will be removed in next major release - i.e. v2.0)

specify what the template should replace. Defaults to false.

  • true - the template will replace the directive's element.
  • false - the template will replace the contents of the directive's element.

-- AngularJS Comprehensive Directive API

From GitHub:

Caitp-- It's deprecated because there are known, very silly problems with replace: true, a number of which can't really be fixed in a reasonable fashion. If you're careful and avoid these problems, then more power to you, but for the benefit of new users, it's easier to just tell them "this will give you a headache, don't do it".

-- AngularJS Issue #7636

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • Thanks @gergeawg I have added the `scope: true,` but this still only removes a single row, despite how many rows are available to delete. – Dan Hodson Apr 08 '16 at 14:52
  • please see this plunkr which better illustrates the issue https://plnkr.co/edit/H5fvWmDLmOcnADlxELOo?p=preview – Dan Hodson Apr 08 '16 at 15:26
  • You didn't tell us you were using `replace: true` on a sibling directive. See the update to my answer. – georgeawg Apr 08 '16 at 22:21
0

To fix your problem, set your filterRow directive's scope to true.

app.directive('filterRow', function() {
        return {
            scope: true,
            replace: true,
            restrict: 'E',
            templateUrl: 'filter-row.html',
        };
});

app.directive('deleteFilter', function() {
        return {
            restrict: 'A',
            scope: true,
            link: function(scope, element) {

                // Scope function to delete a filter row from the DOM
                scope.deleteFilter = function() {
                    console.log("Deleting",element);
                    // Remove the directive element

                    element.remove();
                };
            }
        };
});

Basically setting it to true will allow it to create a new instance of the row. When set to false, there will be only one instance of the row and everytime you click on delete, it will remove the last row that was created.

Hoyen
  • 2,511
  • 1
  • 12
  • 13