The right way to dynamically add input field

Hi everyone, I’m new to Meteor so I try to learn it by building a restaurant management webapp. One feature in this app is to add a daily sales for each products. I want to be able to add multiple sales data at a time and here is what I’ve accomplished so far


Here is my code

<template name="salesAdd">
    <div class="row clearfix">
        table...
                <tbody>
                    {{#each salesInputs}}
                        {{> salesItem}}
                    {{/each}}
                </tbody>
            </table>
        </div>
    </div>
</template>  
<template name="salesItem">
        <tr class="salesItem" salesId="{{salesId}}">
            <td><input type="text" name="name" id="name" placeholder="Product Name.." ></td>
            <td><input type="number" name="sales-price" id="sales-price"></td>
            <td><input type="number" name="sales-quantity" id="sales-quantity"></td>
            <td><input type="number" name="sales-total" id="sales-total"></td>
            <td><a type="button" href="#" class="btn btn-success btn-large add-btn">+</a>
                <a type="button" href="#" class="btn btn-danger btn-large delete-btn">-</a>
            </td>
        </tr>
    </template>


Template.salesAdd.onCreated(function() {
    Session.set('salesInputs', [{salesId: 1}]);
});


Template.salesAdd.events({
  'click .add-btn': function() {
        var salesInputs = Session.get('salesInputs');
        var salesId = Math.floor(Math.random() * 1000);

        salesInputs.push({salesId: salesId});
        Session.set('salesInputs', salesInputs);
    },
});

Template.salesItem.events({
  'click .delete-btn': function() {
        var salesId = Template.instance().$('.salesItem').attr('salesId');
        var salesInput = Session.get('salesInputs');

        salesInput = _.reject(salesInput, function(x) {
            return x.salesId == salesId;
        });

        Session.set('salesInputs', salesInput);
    },
});


Template.salesAdd.helpers({
   salesInputs: function() {
        return Session.get('salesInputs');
    },
});

But I came across some problem. When I delete the input row, the row is gone but the value of the deleted row still carry on to other row. In the example below, I deleted 2nd row (name: 722). The row is gone but its value(Quantity 2 and Total 2) passed on to 3rd row (name:978) and so on when delete other row.

Ideally when I delete the row, the value and the row itself should be gone. Is there a better way to this?
Thank you so much

** The original code is from here

2 Likes

Hello! The SO question you link to has been updated and the example, I believe there is a work-around for the problem. The new MeteorPad is here. The short version is you need to pull the data off the page and repopulate it each time an input is destroyed. The new MeteorPad example includes the value in the input template and populates the session variable with it each time an input is destroyed.

Would love to hear feedback if there is a better way to work around the issue than that.

PS sorry this reply is so late, but perhaps it will help somebody out down the line.

The MeteorPad is down since Mike pulled the project. Any chance someone has the code or could explain with an example? I’m encountering this same issue…

Since you are using jQuery you can use the jQuery remove method to take the element out of DOM. I used the same. It’s working

I’m having this same exact issue! My very hacky workaround has been to do the following

  • Copy array from session
  • Edit the copied array
  • Clear Session value
  • Set Session value to copied array with a timeout of zero
'click .delete-btn': function() {
        var salesId = Template.instance().$('.salesItem').attr('salesId');
        var salesInput = Session.get('salesInputs');

        salesInput = _.reject(salesInput, function(x) {
            return x.salesId == salesId;
        });
        
        Session.set('salesInputs', false);

        setTimeout(() => Session.set('salesInputs', salesInput), 0);
    },

I would prefer to find a better approach to this if anyone has any ideas.