jQuery UI 可排序刷新错误 - 如何刷新动态添加的可排序元素?
jQuery UI Sortable Refresh Error - How to Refresh Dynamically Added Sortable Elements?
gif:
- 页面加载正在初始化我的可排序代码(下)
- 添加一个部分按钮(与此问题无关)
- 向该部分添加一课(动态,页面加载时元素不存在,重要!)
- 该课程无法排序,因为它是动态创建的
- 在控制台中,我冗余地粘贴了我的整个可排序初始化程序
- 课程变得可排序(根据需要)
我的问题:
创建动态元素时,如何正确“刷新”或为新元素提供我已初始化的可排序项目所具有的所有属性和事件(选项?)。
我的 GIF 的最简单 HTML 伪代码:
<div>
<ul class="sortable-sections">
<li class="section">
<ul class="sortable-lessons">
<li>Item 1</li>
</ul>
</li>
</ul>
</div>
有没有办法说(使用 jQuery),“在页面加载时加载或使用 class sortable-lessons
动态创建的任何项目都是可排序的项目”?
我的可排序代码:
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
placeholder: 'placeholder',
items: "li:not(.unsortable)",
forcePlaceholderSize: true,
start: function( event, ui ) {
$(ui.item).addClass("yellow");
},
stop: function(event, ui) {
$(ui.item).removeClass("yellow");
}
});
我的努力:
我想也许在我的函数添加新课后,我可以调用:
$( ".sortable-lessons" ).sortable( "refresh" );
但这会引发错误,我不知道为什么。
错误:
jquery.min.js:2 Uncaught Error: cannot call methods on sortable prior to initialization;
attempted to call method 'refresh'
at Function.error (jquery.min.js:2)
at HTMLUListElement.<anonymous> (jquery-ui.min.js:6)
at Function.each (jquery.min.js:2)
at S.fn.init.each (jquery.min.js:2)
at S.fn.init.t.fn.<computed> [as sortable] (jquery-ui.min.js:6)
at <anonymous>:1:26
从字面上看,documentation on refresh 似乎表明这正是 ("refresh")
方法的用途:
refresh()
Refresh the sortable items. Triggers the reloading of all sortable
items, causing new items to be recognized. This method does not accept
any arguments. Code examples: Invoke the refresh method:
$( ".selector" ).sortable( "refresh" );
我发现的一个简单愚蠢的解决方案 (Refresh list after adding an item with jQuery UI sortable plugin) 提到再次执行整个可排序初始化程序。 当然这是错误的做法。我想以正确的方式做到这一点。
Others call destroy 在原来的基础上,然后重新构建。同样,这似乎不是正确的方法。
编辑/更新可重现的例子
let sectionId = 1;
let lessonId = 1;
$('.sortable-sections').sortable();
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
items: "li",
});
function addSection(id) {
const item = '' +
'<li class="section" id="' + id + '">' +
'<span>section ' + id + ' <button class="add-lesson">Add lesson</button></span>' +
'<ul class="sortable-lessons"></ul>' +
'</li>';
$('.sortable-sections').append(item);
}
$('body').on('click', '#add-section', function () {
addSection(sectionId);
sectionId+=1;
});
function addLesson(sectionId, lessonId) {
const section = $('#' + sectionId);
const item = '<li class="lesson"><div class="border">lesson ' + lessonId + '</div></li>';
section.find('ul.sortable-lessons').append(item);
$('.sortable-lessons').sortable('refresh');
}
$('body').on('click', '.add-lesson', function () {
const section_id = $(this).closest('.section').attr('id');
addLesson(section_id, lessonId);
lessonId+=1;
});
.border {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button id="add-section">Add Section</button>
<ul class="sortable-sections">
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</body>
</html>
但是当不存在任何部分或课程时,该示例是从头开始的。
下面是一些部分和课程存在的示例。
- 添加新部分
- 尝试在该部分添加新课程
let sectionId = 7;
let lessonId = 12;
$('.sortable-sections').sortable();
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
items: "li",
});
function initializeSortableLessons() {
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
items: "li",
});
}
function addSection(id) {
const item = '' +
'<li class="section" id="' + id + '">' +
'<span>section ' + id + ' <button class="add-lesson">Add lesson</button></span>' +
'<ul class="sortable-lessons"></ul>' +
'</li>';
$('.sortable-sections').append(item);
}
$('body').on('click', '#add-section', function () {
addSection(sectionId);
sectionId+=1;
});
function addLesson(sectionId, lessonId) {
const section = $('#' + sectionId);
const item = '<li class="lesson"><div style="border: 1px solid black;">lesson ' + lessonId + '</div></li>';
section.find('ul.sortable-lessons').append(item);
$('.sortable-lessons').sortable('refresh');
}
$('body').on('click', '.add-lesson', function () {
const section_id = $(this).closest('.section').attr('id');
addLesson(section_id, lessonId);
lessonId+=1;
});
.border {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button id="add-section">Add Section</button>
<ul class="sortable-sections ui-sortable">
<li class="section" id="1"><span>section 1 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"></ul></li><li class="section" id="2"><span>section 2 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li><li class="section" id="3"><span>section 3 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"></ul></li><li class="section" id="4"><span>section 4 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li><li class="section" id="5" style=""><span>section 5 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li><li class="section" id="6" style=""><span>section 6 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li></ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</body>
</html>
考虑以下问题。您必须将新的 <ul>
初始化为 Sortable。这样,当您添加 <li>
并调用 refresh
时,它已经被初始化为 Sortable。
$(function() {
function addLesson(event) {
var section = $(this).closest("li");
var item = $("<li>", {
class: "lesson"
});
$("<div>").css("border", "1px solid black").html("Lesson " + ($(".lesson").length + 1)).appendTo(item);
$('ul.sortable-lessons', section).append(item).sortable('refresh');
}
function addSection(props, target) {
var item = $("<li>", props);
$("<span>").html("Section " + props.id + " ").appendTo(item);
$("<button>", {
class: "add-lesson"
}).html("Add Lesson").appendTo($("span", item));
$("<ul>", {
class: "sortable-lessons"
}).appendTo(item).sortable({
connectWith: ".sortable-lessons"
});
if (target === undefined) {
item.appendTo($(".sortable-sections"));
$(".sortable-sections").sortable("refresh");
} else {
item.appendTo(target);
if ($(target).hasClass("ui-sortable")) {
$(target).sortable("refresh");
}
}
}
$('.sortable-sections').sortable();
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons"
});
$('body').on('click', '#add-section', function() {
addSection({
id: $(".section").length + 1
});
});
$('body').on('click', '.add-lesson', addLesson);
});
.border {
border: 1px solid black;
}
<div>
<button id="add-section">Add Section</button>
<ul class="sortable-sections ui-sortable">
<li class="section" id="1"><span>section 1 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons"></ul>
</li>
<li class="section" id="2"><span>section 2 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
<li class="section" id="3"><span>section 3 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons"></ul>
</li>
<li class="section" id="4"><span>section 4 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
<li class="section" id="5" style=""><span>section 5 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
<li class="section" id="6" style=""><span>section 6 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
gif:
- 页面加载正在初始化我的可排序代码(下)
- 添加一个部分按钮(与此问题无关)
- 向该部分添加一课(动态,页面加载时元素不存在,重要!)
- 该课程无法排序,因为它是动态创建的
- 在控制台中,我冗余地粘贴了我的整个可排序初始化程序
- 课程变得可排序(根据需要)
我的问题:
创建动态元素时,如何正确“刷新”或为新元素提供我已初始化的可排序项目所具有的所有属性和事件(选项?)。
我的 GIF 的最简单 HTML 伪代码:
<div>
<ul class="sortable-sections">
<li class="section">
<ul class="sortable-lessons">
<li>Item 1</li>
</ul>
</li>
</ul>
</div>
有没有办法说(使用 jQuery),“在页面加载时加载或使用 class sortable-lessons
动态创建的任何项目都是可排序的项目”?
我的可排序代码:
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
placeholder: 'placeholder',
items: "li:not(.unsortable)",
forcePlaceholderSize: true,
start: function( event, ui ) {
$(ui.item).addClass("yellow");
},
stop: function(event, ui) {
$(ui.item).removeClass("yellow");
}
});
我的努力:
我想也许在我的函数添加新课后,我可以调用:
$( ".sortable-lessons" ).sortable( "refresh" );
但这会引发错误,我不知道为什么。
错误:
jquery.min.js:2 Uncaught Error: cannot call methods on sortable prior to initialization;
attempted to call method 'refresh'
at Function.error (jquery.min.js:2)
at HTMLUListElement.<anonymous> (jquery-ui.min.js:6)
at Function.each (jquery.min.js:2)
at S.fn.init.each (jquery.min.js:2)
at S.fn.init.t.fn.<computed> [as sortable] (jquery-ui.min.js:6)
at <anonymous>:1:26
从字面上看,documentation on refresh 似乎表明这正是 ("refresh")
方法的用途:
refresh()
Refresh the sortable items. Triggers the reloading of all sortable items, causing new items to be recognized. This method does not accept any arguments. Code examples: Invoke the refresh method:
$( ".selector" ).sortable( "refresh" );
我发现的一个简单愚蠢的解决方案 (Refresh list after adding an item with jQuery UI sortable plugin) 提到再次执行整个可排序初始化程序。 当然这是错误的做法。我想以正确的方式做到这一点。
Others call destroy 在原来的基础上,然后重新构建。同样,这似乎不是正确的方法。
编辑/更新可重现的例子
let sectionId = 1;
let lessonId = 1;
$('.sortable-sections').sortable();
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
items: "li",
});
function addSection(id) {
const item = '' +
'<li class="section" id="' + id + '">' +
'<span>section ' + id + ' <button class="add-lesson">Add lesson</button></span>' +
'<ul class="sortable-lessons"></ul>' +
'</li>';
$('.sortable-sections').append(item);
}
$('body').on('click', '#add-section', function () {
addSection(sectionId);
sectionId+=1;
});
function addLesson(sectionId, lessonId) {
const section = $('#' + sectionId);
const item = '<li class="lesson"><div class="border">lesson ' + lessonId + '</div></li>';
section.find('ul.sortable-lessons').append(item);
$('.sortable-lessons').sortable('refresh');
}
$('body').on('click', '.add-lesson', function () {
const section_id = $(this).closest('.section').attr('id');
addLesson(section_id, lessonId);
lessonId+=1;
});
.border {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button id="add-section">Add Section</button>
<ul class="sortable-sections">
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</body>
</html>
但是当不存在任何部分或课程时,该示例是从头开始的。
下面是一些部分和课程存在的示例。
- 添加新部分
- 尝试在该部分添加新课程
let sectionId = 7;
let lessonId = 12;
$('.sortable-sections').sortable();
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
items: "li",
});
function initializeSortableLessons() {
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons",
items: "li",
});
}
function addSection(id) {
const item = '' +
'<li class="section" id="' + id + '">' +
'<span>section ' + id + ' <button class="add-lesson">Add lesson</button></span>' +
'<ul class="sortable-lessons"></ul>' +
'</li>';
$('.sortable-sections').append(item);
}
$('body').on('click', '#add-section', function () {
addSection(sectionId);
sectionId+=1;
});
function addLesson(sectionId, lessonId) {
const section = $('#' + sectionId);
const item = '<li class="lesson"><div style="border: 1px solid black;">lesson ' + lessonId + '</div></li>';
section.find('ul.sortable-lessons').append(item);
$('.sortable-lessons').sortable('refresh');
}
$('body').on('click', '.add-lesson', function () {
const section_id = $(this).closest('.section').attr('id');
addLesson(section_id, lessonId);
lessonId+=1;
});
.border {
border: 1px solid black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button id="add-section">Add Section</button>
<ul class="sortable-sections ui-sortable">
<li class="section" id="1"><span>section 1 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"></ul></li><li class="section" id="2"><span>section 2 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li><li class="section" id="3"><span>section 3 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"></ul></li><li class="section" id="4"><span>section 4 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li><li class="section" id="5" style=""><span>section 5 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li><li class="section" id="6" style=""><span>section 6 <button class="add-lesson">Add lesson</button></span><ul class="sortable-lessons"><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li><li class="lesson"><div style="border: 1px solid black;">lesson 1</div></li></ul></li></ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</body>
</html>
考虑以下问题。您必须将新的 <ul>
初始化为 Sortable。这样,当您添加 <li>
并调用 refresh
时,它已经被初始化为 Sortable。
$(function() {
function addLesson(event) {
var section = $(this).closest("li");
var item = $("<li>", {
class: "lesson"
});
$("<div>").css("border", "1px solid black").html("Lesson " + ($(".lesson").length + 1)).appendTo(item);
$('ul.sortable-lessons', section).append(item).sortable('refresh');
}
function addSection(props, target) {
var item = $("<li>", props);
$("<span>").html("Section " + props.id + " ").appendTo(item);
$("<button>", {
class: "add-lesson"
}).html("Add Lesson").appendTo($("span", item));
$("<ul>", {
class: "sortable-lessons"
}).appendTo(item).sortable({
connectWith: ".sortable-lessons"
});
if (target === undefined) {
item.appendTo($(".sortable-sections"));
$(".sortable-sections").sortable("refresh");
} else {
item.appendTo(target);
if ($(target).hasClass("ui-sortable")) {
$(target).sortable("refresh");
}
}
}
$('.sortable-sections').sortable();
$('.sortable-lessons').sortable({
connectWith: ".sortable-lessons"
});
$('body').on('click', '#add-section', function() {
addSection({
id: $(".section").length + 1
});
});
$('body').on('click', '.add-lesson', addLesson);
});
.border {
border: 1px solid black;
}
<div>
<button id="add-section">Add Section</button>
<ul class="sortable-sections ui-sortable">
<li class="section" id="1"><span>section 1 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons"></ul>
</li>
<li class="section" id="2"><span>section 2 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
<li class="section" id="3"><span>section 3 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons"></ul>
</li>
<li class="section" id="4"><span>section 4 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
<li class="section" id="5" style=""><span>section 5 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
<li class="section" id="6" style=""><span>section 6 <button class="add-lesson">Add lesson</button></span>
<ul class="sortable-lessons">
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
<li class="lesson">
<div style="border: 1px solid black;">lesson 1</div>
</li>
</ul>
</li>
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>