Reputation: 2245
I have a javascript object which i am instantiating for each instance of a dom object. My code looks something like this
let div = null;
$(function() {
div = {
init: function(container) {
this.loadDom(container);
this.loadEvents();
},
loadDom:function(container) {
this.$container = $(container);
this.$buttons = this.$container.find('.button');
this.$textPanel = $('.text-panel')
},
loadEvents: function() {
let that = this;
// output the item's id. This works correctly
that.$textPanel.append(that.$container.attr('id') + '<br>');
this.$buttons.on('click', function() {
// output the item's id. This always outputs the last item
that.$textPanel.append(that.$container.attr('id') + '<br>');
});
}
};
let divs = $('.item');
if(divs.length > 0) {
divs.each(function(){
div.init(this);
})
}
});
I expect there to be one object created for each div with a class of 'item', and all the functions within that object to apply to that one div. i.e. when you click the red div, the container's id should be shown in the panel below.
In the loadEvents function, I list the id of the current div. This is run immediately and correctly lists "modal-1" and "modal-2". But when I run the same command after a button click, the id of the last div is always displayed rather than the current div.
How can I make the button click work so the id of the correct div is shown?
Thanks
Upvotes: 2
Views: 40
Reputation: 7446
I have reviewed the code by making div
a function instead, so that the scope of each div will be unique and the events registered will belong to the div itself.
Other than that, the variable that
was implicitly global, so I've added let
before it so that it's correctly scoped.
It now works as intended
let div = null;
$(function() {
div = function(){
return {
init: function(container) {
this.loadDom(container);
this.loadEvents();
},
loadDom:function(container) {
this.$container = $(container);
console.log('con')
this.$buttons = this.$container.find('.button');
this.$textPanel = $('.text-panel')
},
loadEvents: function() {
let that = this;
// output the item's id. This works correctly
that.$textPanel.append(that.$container.attr('id') + '<br>');
this.$buttons.on('click', function() {
// output the item's id. This always outputs the last item
that.$textPanel.append(that.$container.attr('id') + '<br>');
});
}
}
}
let divs = $('.item');
if(divs.length > 0) {
divs.each(function(){
const _d = new div();
_d.init(this);
})
}
})
.container {
display: grid;
grid-gap: 30px;
grid-template-columns: 1fr 1fr;
}
.item {
border: 1px dotted green;
height: 100px;
width: 100%;
display: inline-block;
text-align: center;
}
.button {
height: 50px;
width: 50px;
background: red;
cursor: pointer
}
.text-panel {
border: 1px dotted black;
height: 200px;
grid-column: 1/3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item" id="modal-1">
<div class="button">click me</div>
modal-1
</div>
<div class="item" id="modal-2">
<div class="button">click me</div>
modal-2
</div>
<div class="text-panel"></div>
</div>
Upvotes: 1