Reputation: 2659
I am trying to get .sortable
from jQuery UI to work but it is only working for my first item, when I dynamically add new ones, it stops working.
I found this: http://api.jqueryui.com/sortable/#method-refresh which should refresh everything and recognize new items, but when I use that I get the error:
Uncaught Error: cannot call methods on sortable prior to initialization; attempted to call method 'refresh'
What can I do?
My code:
// HTML template for new fields
const template = `<div class="row sortwrap">
<div class="col-md-8">
<input type="text" name="category[]" placeholder="" class="form-control name_list catinput" />
<i class="mdi mdi-sort dragndrop"></i>
<div class="questionlist">
<div class="row">
<div class="col-md-8">
<input type="text" name="question[]" placeholder="1. Voeg een vraag toe" class="form-control name_list questioninput" />
</div>
<div class="col-md-4">
<button class="btn btn-success questionbutton">Extra vraag</button>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<button id="addcategory" class="btn btn-danger btn_remove">X</button>
</div>
</div>`;
const vraagTemplate = `<div class="row">
<div class="col-md-8">
<input type="text" name="question[]" class="form-control name_list questioninput" />
</div>
<div class="col-md-4">
<button class="btn btn-danger btn_remove">X</button>
</div>
</div>`;
$('.sortwrap').sortable();
// Count numbers and change accordingly when field is deleted
function updatePlaceholders() {
// Sortable code
$('.sortwrap').sortable("refresh");
$('#dynamic_field input[name^=cat]').each(function(i) {
$(this).attr("placeholder", i + 1 + ". Voeg een categorie toe");
});
$('#dynamic_field .sortwrap').each(function(i) {
$(this).attr("id", i + 1);
});
$('#dynamic_field .questionlist').each(function() {
$(this).find('input[name^=qu]').each(function(i) {
$(this).attr("placeholder", i + 1 + ". Voeg een vraag toe");
});
});
}
// Append category template
$('#addcategory').click(function() {
$('#dynamic_field').append($(template));
updatePlaceholders();
});
// Append question template
$('#dynamic_field').on('click', '.questionbutton', function() {
$ql = $(this).closest('.questionlist');
$ql.append($(vraagTemplate));
updatePlaceholders();
});
// Delete
$('#dynamic_field').on('click', '.btn_remove', function() {
$(this).closest('.row').remove();
updatePlaceholders();
});
If I remove the line that says refresh in my function and only have the one .sortable
in my code then I can drag all items even new ones but nothing is dropping. So I can drag but not sort/drop.
Upvotes: 1
Views: 4266
Reputation: 34217
I think this is on where you attach your sort. I used a wrapper here to do so.
Note I turned off the refresh due to where I attached it as it seems to not need that given that attachment point.
// HTML template for new fields
const template = '<div class="row sortwrap"> <div class="col-md-8"> <input type="text" name="category[]" placeholder="" class="form-control name_list catinput" /> <i class="mdi mdi-sort dragndrop"></i> <div class="questionlist"> <div class="row"> <div class="col-md-8"> <input type="text" name="question[]" placeholder="1. Voeg een vraag toe" class="form-control name_list questioninput" /> </div> <div class="col-md-4"> <button class="btn btn-success questionbutton">Extra vraag</button> </div> </div> </div> </div> <div class="col-md-4"> <button id="addcategory" class="btn btn-danger btn_remove">X</button> </div> </div>';
const vraagTemplate = '<div class="row"> <div class="col-md-8"> <input type="text" name="question[]" class="form-control name_list questioninput" /> </div> <div class="col-md-4"> <button class="btn btn-danger btn_remove">X</button> </div> </div>';
// Count numbers and change accordingly when field is deleted
function updatePlaceholders() {
// Sortable code
// $('#dynamic_field').sortable( "refresh" );
let df = $('#dynamic_field');
df.find('input[name^=cat]').each(function(i) {
$(this).attr("placeholder", i + 1 + ". Voeg een categorie toe");
});
df.find('.sortwrap').each(function(i) {
$(this).attr("id", i + 1);
});
df.find('.questionlist').each(function() {
$(this).find('input[name^=qu]').each(function(i) {
$(this).attr("placeholder", i + 1 + ". Voeg een vraag toe");
});
});
}
// Append question template
$('#dynamic_field').on('click', '.questionbutton', function() {
let $ql = $(this).closest('.questionlist');
$ql.append($(vraagTemplate));
updatePlaceholders();
});
// Delete
$('#dynamic_field').on('click', '.btn_remove', function() {
$(this).closest('.row').remove();
updatePlaceholders();
});
$('#addcategory').on('click', function() {
let t = $(template)
$('#dynamic_field').append(t);
updatePlaceholders();
});
$(function() {
$('#addcategory').trigger('click');
$('#dynamic_field').sortable();
});
.sortwrap{border: solid green 1px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div>
<button id="addcategory">add</button>
</div>
<div id="dynamic_field"></div>
Upvotes: 1
Reputation: 3932
As mentioned above this will work fine This looks promising:
http://api.jqueryui.com/sortable/#method-refresh
it seems to imply that you can just add an item to a sortable, then call
$('#mysortable').sortable('refresh')
to recognize it.
var counter = 1;
function appendThing() {
$("<li id='Text" + counter + "' class='ui-state-default'>Text" + counter + "</li>").appendTo($("#mySortable"));
$("#mySortable").sortable({ refresh: mySortable })
counter++;
};
please take a look into this
https://jsfiddle.net/6ztrdg9n/
Upvotes: 0