Ferry Sanjaya
Ferry Sanjaya

Reputation: 224

Jquery plugin not work properly on multiple element

I have created my own simple jQuery plugin, but I'm having some problem when I put 2 elements and call the plugin on each element.

This is my .js code:

function fTable(element,options) {
    self          = this;
    this.$element = $(element);
    this.table    = $(this.$element).find('table');
    this.thead    = $(this.table).find('thead');
    this.tbody    = $(this.table).find('tbody');
    column        = options.column;

    this.defaults = {

    }

    // Merge default options with user options
    this.options = $.extend(true, {}, this.defaults, options);
    this.init();
}

fTable.prototype = {
    init : function() {
        self = this;
        this.td = $(this.thead).find('tr td:first');
        $(this.td).html('<a class="add">Plus</a>');
        this.bindEvents();
    },

    bindEvents : function() { 
        self = this;
        console.log(this.table);
        $(this.table).on('click', '.add', function(){
            $row =  '<tr>';
            $row += '<td></td>';
            
            $.each(column, function(index, value){
                $row += '<td><input type="text" value="" name='+value.name+' '+value.prop+'></td>';
            });

            $row += '</tr>';
            console.log(self);
            $($row).appendTo(self.table);
            lastTR = $(self.tbody).find('tr:last');
            $(lastTR).find('td:first').html('<a class="remove">Remove</a>');
        });

        $(this.table).on('click', '.remove', function(){
            row = $(this).closest('tr');
            $(row).remove();
        });
    }
}

$.fn.fTable = function(options) {
    return this.each(function() {
        new fTable(this,options);
    });
}

$('.crud').fTable({
        column:[
            {'type':'text','name':'NIK','prop':'disabled'},
            {'type':'text','name':'NAME','prop':''},
        ]
    }); 

$('.crud2').fTable({
    column:[
        {'type':'text','name':'NIK','prop':'disabled'},
        {'type':'text','name':'NAME','prop':''},
    ]
}); 

HTML :

<div class="crud">
    <table class="table table-bordered">
        <thead>
            <tr>
                <td style="width:10%"></td>
                <td>NIK</td>
                <td>Name</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td>1</td>
                <td>Ardhi</td>
            </tr>
            <tr>
                <td></td>
                <td>2</td>
                <td>Mega</td>
            </tr>
        </tbody>
    </table>
</div>

<div class="crud2">
    <table class="table table-bordered">
        <thead>
            <tr>
                <td style="width:10%"></td>
                <td>NIK</td>
                <td>Name</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td>1</td>
                <td>Zaphire</td>
            </tr>
            <tr>
                <td></td>
                <td>2</td>
                <td>Rexa</td>
            </tr>
        </tbody>
    </table>
</div>

The problem is when I click the 'plus' on 1st table(class='crud') it will add new row to 2nd table(class='crud2') instead of 1st table(class='crud')

Any help?

Upvotes: 1

Views: 32

Answers (1)

SomeShinyObject
SomeShinyObject

Reputation: 7801

You have a problem with scope. In your bindEvents prototype function, you declare self=this but you're not referring to the current scope. You actually have a scope problem everywhere. Please review JavaScript scope.

Change that line to either var self or even better let self to grab the functions scope rather than anything higher (global) or a self that was previously declared.

function fTable(element,options){
    let self      = this; // you omitted let or var here
    this.$element = $(element);
    this.table    = $(this.$element).find('table');
    this.thead    = $(this.table).find('thead');
    this.tbody    = $(this.table).find('tbody');
    this.column   = options.column; // it was omitted here also but for sake of consistency, I applied column as a member to fTable.

    this.defaults = {

    }

    //Merge default options with user options
    this.options = $.extend(true, {}, this.defaults, options);
    this.init();
}

fTable.prototype = {
    init : function(){
        let self = this; // omitted here too
        this.td = $(this.$element).find('tr td:first');
        $(this.td).html('<a class="add">Plus</a>');
        this.bindEvents();
    },

    bindEvents : function(){
        let self = this;
        $(this.table).on('click', '.add', function(){
            let $row =  '<tr>';
            $row += '<td></td>';

            $.each(self.column, function(index, value){
                $row += '<td><input type="text" value="" name='+value.name+' '+value.prop+'></td>';
            });

            $row += '</tr>';
            $($row).appendTo(self.table);
            let lastTR = $(self.tbody).find('tr:last');
            $(lastTR).find('td:first').html('<a class="remove">Remove</a>');
        });

        $(this.table).on('click', '.remove', function(){
            let row = $(self).closest('tr');
            $(row).remove();
        });
    }
}

$.fn.fTable = function(options){
    var self = this; // and here
    return this.each(function(){
        new fTable(self,options);
    });
}

$('.crud').fTable({
        column:[
            {'type':'text','name':'NIK','prop':'disabled'},
            {'type':'text','name':'NAME','prop':''},
        ]
    }); 

$('.crud2').fTable({
    column:[
        {'type':'text','name':'NIK','prop':'disabled'},
        {'type':'text','name':'NAME','prop':''},
    ]
}); 

Upvotes: 1

Related Questions