带无限滚动的 Select2 组
Select2 group with Infinite scroll
我正在使用无限滚动的 select2 组选项,数据通过 Ajax 每页 10 调用来获取。这里出现了一些问题,假设用户 1 有 15 个数据,用户 2 有 15 个数据,首先10 个数据来自用户 1 和下一页 10(用户 1 的 5 个数据和用户 2 的 5 个数据)。数据获取没问题,但问题是用户 1 组显示双倍。如何防止双重显示我的 select2 选项组?有没有办法重新做一个选项组?
HTML 代码
<div class="container">
<form id="frm">
<h1>Solution 1</h1>
<div class="row">
<div class="col-4">
<div class="form-group">
<label for="tagInput">Get data by ajax calling</label>
<select class="form-control" id="pictures_tag_input">
</select>
<small class="form-text text-muted"><p class="text-info">Infinite Scroll</p></small>
</div>
</div>
</div>
</form>
</div>
JS 代码
$(document).ready(function() {
// solution 1
//example.com/articles?page[number]=3&page[size]=1
http: $("#pictures_tag_input").select2({
placeholder: "Search for options",
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: true,
delay: 250,
minimumInputLength: 2,
data: function(params) {
// console.log(params.page || 1);
return {
q: params.term, // search term
_page: params.page || 1,
_limit: 10 // page size
};
},
processResults: function(data, params) {
params.page = params.page || 1;
var datx = getNestedChildren(data);
// console.log(datx);
return {
results: datx,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function getNestedChildren(list) {
var roots = [];
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (roots.length === 0) {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
roots.push(obj);
} else {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
var rootArray = $.map(roots, function(val, i) {
var vl = "User " + node.userId;
if (val.text === vl) return val;
else return undefined;
});
if (rootArray.length > 0) {
var obj1 = {
id: node.id,
text: node.title
};
rootArray[0].children.push(obj1);
} else {
roots.push(obj);
}
}
}
return roots;
}
});
可能是数据源问题
您调用用户 1 .... 服务器 return a 1
你调用用户 2 .... 服务器 return a 1
您呼叫用户 3 .... 服务器 return a 2
你叫用户4....服务器return一个2
你叫用户5....服务器return一个3
您呼叫用户 6 .... 服务器 return a 3
curent_user = 1;
$(document).ready(function() {
http: $("#pictures_tag_input").select2({
placeholder: "Search for options",
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: false,
minimumInputLength: 2,
data: function(params) {
console.log("params",params || 1);
return {
q: params.term, // search term
_page: curent_user,
_limit: 10 // page size
};
},
processResults: function(data, params) {
curent_user += 2;
var datx = getNestedChildren(data);
console.log("data: ", data);
return {
results: datx,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function getNestedChildren(list) {
var roots = [];
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (roots.length === 0) {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
roots.push(obj);
} else {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
var rootArray = $.map(roots, function(val, i) {
var vl = "User " + node.userId;
if (val.text === vl) return val;
else return undefined;
});
if (rootArray.length > 0) {
var obj1 = {
id: node.id,
text: node.title
};
rootArray[0].children.push(obj1);
} else {
roots.push(obj);
}
}
}
return roots;
}
});
所以如果你跳过一步
您调用用户 1 .... 服务器 return a 1
您呼叫用户 3 .... 服务器 return a 2
你叫用户5....服务器return一个3
只需尝试使用以下代码
templateResult: function(data) {
if (typeof data.children != 'undefined') {
$(".select2-results__group").each(function() {
if (data.text == $(this).text()) {
return data.text = '';
}
});
}
return data.text;
}
注意:需要从服务器端进行分组,否则您必须从客户端进行主详细信息。
我刚刚找到了一个更好的解决方案,它不会导致(重复的)optgroup 被呈现为空选项:
processResults: function( json, params ){
setTimeout( function() {
var $prevOptions = false;
var $prevGroup = false;
// loop
$('.select2-results__option[role="group"]').each(function(){
// vars
var $options = $(this).children('ul');
var $group = $(this).children('strong');
// compare to previous
if( $prevGroup && $prevGroup.text() === $group.text() ) {
$prevOptions.append( $options.children() );
$(this).remove();
return;
}
// update vars
$prevOptions = $options;
$prevGroup = $group;
});
}, 1 );
return json;
}
Advanced Custom Fields
对其 WordPress 插件使用完全相同的代码来解决此问题,ajax-加载和分组来自不同 post 类型的 posts .
已接受的答案对我不起作用,我不明白为什么它会起作用。 $.each
中的 return 不会 templateResult()
函数中的 return。
这是一种对我有用的方法。
- 不需要在javascript端通过
getNestedChildren(list)
构建嵌套列表。相反,在服务器端构建它要容易得多。
- 可以使用 templateResult 选项自定义下拉列表中搜索结果的外观(选项和选项组)。我通过这个选项删除了重复的 optgroups 和标签。
检查代码的templateResult: formatOptions,
部分
$(document).ready(function() {
$("#pictures_tag_input").select2({
placeholder: "Search for options",
templateResult: formatOptions,
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: true,
delay: 250,
minimumInputLength: 2,
data: function(params) {
return {
q: params.term,
_page: params.page || 1,
_limit: 10
};
},
processResults: function(data, params) {
params.page = params.page || 1;
return {
results: data,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function formatOptions(item, container, $el) {
// optgroups section
if (item.children && item.children.length > 0) {
// don't format the repeated optgroups!
if ($(".select2-results__group").text() === item.text) {
return;
}
if ($('[aria-label="' + item.text + '"]').length > 0) {
return;
}
// the first occasion of the given optgroup
return $el;
}
// options section
// here you can implement your own logic
// if you want to customise the output of the options
$el.addClass('something-special-result result');
return $el;
}
});
我正在使用无限滚动的 select2 组选项,数据通过 Ajax 每页 10 调用来获取。这里出现了一些问题,假设用户 1 有 15 个数据,用户 2 有 15 个数据,首先10 个数据来自用户 1 和下一页 10(用户 1 的 5 个数据和用户 2 的 5 个数据)。数据获取没问题,但问题是用户 1 组显示双倍。如何防止双重显示我的 select2 选项组?有没有办法重新做一个选项组?
HTML 代码
<div class="container">
<form id="frm">
<h1>Solution 1</h1>
<div class="row">
<div class="col-4">
<div class="form-group">
<label for="tagInput">Get data by ajax calling</label>
<select class="form-control" id="pictures_tag_input">
</select>
<small class="form-text text-muted"><p class="text-info">Infinite Scroll</p></small>
</div>
</div>
</div>
</form>
</div>
JS 代码
$(document).ready(function() {
// solution 1
//example.com/articles?page[number]=3&page[size]=1
http: $("#pictures_tag_input").select2({
placeholder: "Search for options",
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: true,
delay: 250,
minimumInputLength: 2,
data: function(params) {
// console.log(params.page || 1);
return {
q: params.term, // search term
_page: params.page || 1,
_limit: 10 // page size
};
},
processResults: function(data, params) {
params.page = params.page || 1;
var datx = getNestedChildren(data);
// console.log(datx);
return {
results: datx,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function getNestedChildren(list) {
var roots = [];
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (roots.length === 0) {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
roots.push(obj);
} else {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
var rootArray = $.map(roots, function(val, i) {
var vl = "User " + node.userId;
if (val.text === vl) return val;
else return undefined;
});
if (rootArray.length > 0) {
var obj1 = {
id: node.id,
text: node.title
};
rootArray[0].children.push(obj1);
} else {
roots.push(obj);
}
}
}
return roots;
}
});
可能是数据源问题
您调用用户 1 .... 服务器 return a 1
你调用用户 2 .... 服务器 return a 1
您呼叫用户 3 .... 服务器 return a 2
你叫用户4....服务器return一个2
你叫用户5....服务器return一个3
您呼叫用户 6 .... 服务器 return a 3
curent_user = 1;
$(document).ready(function() {
http: $("#pictures_tag_input").select2({
placeholder: "Search for options",
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: false,
minimumInputLength: 2,
data: function(params) {
console.log("params",params || 1);
return {
q: params.term, // search term
_page: curent_user,
_limit: 10 // page size
};
},
processResults: function(data, params) {
curent_user += 2;
var datx = getNestedChildren(data);
console.log("data: ", data);
return {
results: datx,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function getNestedChildren(list) {
var roots = [];
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (roots.length === 0) {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
roots.push(obj);
} else {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
var rootArray = $.map(roots, function(val, i) {
var vl = "User " + node.userId;
if (val.text === vl) return val;
else return undefined;
});
if (rootArray.length > 0) {
var obj1 = {
id: node.id,
text: node.title
};
rootArray[0].children.push(obj1);
} else {
roots.push(obj);
}
}
}
return roots;
}
});
所以如果你跳过一步
您调用用户 1 .... 服务器 return a 1
您呼叫用户 3 .... 服务器 return a 2
你叫用户5....服务器return一个3
只需尝试使用以下代码
templateResult: function(data) {
if (typeof data.children != 'undefined') {
$(".select2-results__group").each(function() {
if (data.text == $(this).text()) {
return data.text = '';
}
});
}
return data.text;
}
注意:需要从服务器端进行分组,否则您必须从客户端进行主详细信息。
我刚刚找到了一个更好的解决方案,它不会导致(重复的)optgroup 被呈现为空选项:
processResults: function( json, params ){
setTimeout( function() {
var $prevOptions = false;
var $prevGroup = false;
// loop
$('.select2-results__option[role="group"]').each(function(){
// vars
var $options = $(this).children('ul');
var $group = $(this).children('strong');
// compare to previous
if( $prevGroup && $prevGroup.text() === $group.text() ) {
$prevOptions.append( $options.children() );
$(this).remove();
return;
}
// update vars
$prevOptions = $options;
$prevGroup = $group;
});
}, 1 );
return json;
}
Advanced Custom Fields
对其 WordPress 插件使用完全相同的代码来解决此问题,ajax-加载和分组来自不同 post 类型的 posts .
已接受的答案对我不起作用,我不明白为什么它会起作用。 $.each
中的 return 不会 templateResult()
函数中的 return。
这是一种对我有用的方法。
- 不需要在javascript端通过
getNestedChildren(list)
构建嵌套列表。相反,在服务器端构建它要容易得多。 - 可以使用 templateResult 选项自定义下拉列表中搜索结果的外观(选项和选项组)。我通过这个选项删除了重复的 optgroups 和标签。
检查代码的templateResult: formatOptions,
部分
$(document).ready(function() {
$("#pictures_tag_input").select2({
placeholder: "Search for options",
templateResult: formatOptions,
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: true,
delay: 250,
minimumInputLength: 2,
data: function(params) {
return {
q: params.term,
_page: params.page || 1,
_limit: 10
};
},
processResults: function(data, params) {
params.page = params.page || 1;
return {
results: data,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function formatOptions(item, container, $el) {
// optgroups section
if (item.children && item.children.length > 0) {
// don't format the repeated optgroups!
if ($(".select2-results__group").text() === item.text) {
return;
}
if ($('[aria-label="' + item.text + '"]').length > 0) {
return;
}
// the first occasion of the given optgroup
return $el;
}
// options section
// here you can implement your own logic
// if you want to customise the output of the options
$el.addClass('something-special-result result');
return $el;
}
});