3

I have a collection called Rulesets - each ruleset has an array of "rules". I have the following html which displays each ruleset and each rule:

<template name="rulesets">
    {{#each rulesets}}
        {{>rulesetSingle}}
    {{/each}}
</template>

<template name="rulesetSingle">
    {{#each rules}}
         <p class="rule-description">{{this}}
             <a href="#" class="rule-delete-btn">x</a>
         </p>
    {{/each}}
</template>

I want to be able to remove the rule when the user clicks the "rule-delete-btn".
I have the following javascript to do this:

Template.rulesetSingle.event({
    'click .rule-delete-btn': function(e){
        e.preventDefault();
        var array = Rulesets.rules;
        var index = array.indexOf(this);
        array.splice(index, 1);
    }
});

The delete isn't working because the "array" declaration isn't pulling a valid array. How can I find and store the array that contains "this" which is the current rule that needs to be deleted?

Ramsay Lanier
  • 426
  • 6
  • 18
  • Do you want to completely remove that array entry form `Rulesets` collection? – sohel khalifa Jul 11 '13 at 04:31
  • Lets say for example that Rulests.rules is an array containing rule descriptions for 3 rules. I want to be able to delete the selected rule description from the array and have the other 2 still be there. – Ramsay Lanier Jul 11 '13 at 04:53

1 Answers1

3

Assuming your Rulesets.rules array is an array of objects like :

Rulesets : { { title: 'title1', 
               rules : [ {name : 'rule1', description : 'description1'}, 
                         {name : 'rule2', description : 'description2'}
                       ]
             },
             { title: 'title2', 
               rules : [ {name : 'rule1', description : 'description1'}, 
                         {name : 'rule2', description : 'description2'}
                       ]
             } }

First, in your rulesetSingle template, you must assign the _id of that particular document to the <a> like :

<a href="#" name="{{../_id}}"class="rule-delete-btn"> x </a>

Second thing, you are trying to remove rule entry using Array.splice(), this is not possible since the rules is a document inside the collection. You must do update query as Rulesets.update().

If you have done allow update on the server, you can delete this array entry from within the event handler, otherwise you must do Meteor.call() by passing rule an the _id of parent document.

So, the event handler will look something like :

 'click .rule-delete-btn': function(e) {
        e.preventDefault();
        var rule = this;
        var id = e.currentTarget.name;
        Meteor.call('removeRule', id, rule);
  }

On the server:

  Meteor.methods({
    removeRule: function(id, rule){
      Rulesets.update({_id: id}, {$pull : {rules : rule}});
    }
  });
sohel khalifa
  • 5,602
  • 3
  • 34
  • 46
  • Sweet, thanks. I actually went about this by creating a collection of Rules and then storing the ruleset ID in the rule collection - then when the delete button is clicked it removes the rule from the collection. But this would have worked too. I had some other reasons for creating a separate collection. – Ramsay Lanier Jul 13 '13 at 03:52
  • This is the right answer -- but something which tripped me up badly is that the way I have to call the equivalent of "rule" in my code, it was being converted to a string rather than remaining as an object. Now if I do "JSON.parse(rule)" before calling removeRule, it actually works. – nkoren Aug 29 '13 at 15:13