Reputation: 26281
I am cloning an element and adding it to the DOM. I expected that this
within the newly created cloned element would refer to itself, but it appears to refer to the original clone element.
To illustrate, I created the following script. By clicking "cloneIt", a new element is added, and upon clicking the new element, this
refers to the original clone. My desire was for data('type')
to display "added".
How do I clone an element and have the callback pertain to the newly cloned object?
$('.fileupload').fileupload({
start: function (e, data) {
console.log('start', this, $(this).parent().data('type'));
}
})
.on('fileuploadsubmit', function (e, data) {
console.log('fileuploadsubmit', this, $(this).parent().data('type'));
});
$('#cloneIt').click(function () {
$('#clone').clone(true).removeAttr('id').data('type', 'added').appendTo('#container');
});
#clone {
display:none;
}
<button id="cloneIt">cloneIt</button>
<ul id="container">
<li id="clone" data-type="clone">
<input class="fileupload" name="file" type="file" />
</li>
<li data-type="existing">
<input class="fileupload" name="file" type="file" />
</li>
</ul>
Upvotes: 3
Views: 421
Reputation: 19288
It would appear that the start callback's notion of this
gets locked in when .fileupload()
is invoked, and that this
is carried forward to the clone.
Personally I would keep the template LI separate from the live LIs, and never invoke .fileupload()
on it.
HTML
<button id="cloneIt">cloneIt</button>
<ul id="template">
<li data-type="original">
<input class="fileupload" name="file" type="file" />
</li>
</ul>
<ul id="container">
<li data-type="existing">
<input class="fileupload" name="file" type="file" />
</li>
</ul>
CSS
#template {
display:none;
}
Initially, invoke .fileupload()
only on the INPUTs in #container
, and subsequently on any clone of the template after it is made.
Javascript
$('#container .fileupload').fileupload({
start: function (e, data) {
console.log('start', this, $(this).parent().data('type'));
}
}).on('fileuploadsubmit', function (e, data) {
console.log('fileuploadsubmit', this, $(this).parent().data('type'));
});
$('#cloneIt').click(function () {
$('#template li').clone().data('type', 'clone').appendTo('#container').find('.fileupload').fileupload(...);
});
I would recommend this approach with any plugin. Cloning a widgetized element is dangerous. Clone behaviour is not guaranteed to be reliable. With some plugins, you may get away with it; with others, you won't.
Upvotes: 2
Reputation: 9995
http://jsfiddle.net/1as47aeb/5/
Seems like you need to call the fileupload
method from the library again, after creating the DOM object.
If you inspect the DOM in your code, you will see that the attribute is there, added, and you can query it inside your original code after cloning.
EDITCorrected behavior in which both input events called when uploading in clone input.
Upvotes: 1