英文:
jQuery DataTable: How to chain rows() methods to apply multiple conditions?
问题
我不明白为什么 table.rows([selector1]).rows([selector2])
不返回同时满足 selector1 和 selector2 的行。
例如,以下代码忽略了第一个条件 {selected:true}。
table.rows({selected:true}).rows((index, row, node)=>{return row[3]<30}).deselect()
表格源自:https://datatables.net/extensions/select/examples/api/get.html
我可以通过将两个条件组合成一个 rows()
来解决这个问题,但我仍然不明白为什么链式调用 rows()
不起作用,如我所期望的那样。
rows()
方法返回 DataTables.Api,它根据引用提供链式调用的能力。
https://datatables.net/reference/type/DataTables.Api
table.rows((index, row, node)=>{return $(node).hasClass("selected") && row[3]<=30}).deselect()
英文:
I wonder why table.rows([selector1]).rows([selector2]) doesn't return the rows which satisfies the both selector1 and selector2.
For example, the following code ignores the first condtion {selected:true}.
table.rows({selected:true}).rows((index, row, node)=>{return row[3]<30}).deselect()
table source: https://datatables.net/extensions/select/examples/api/get.html
I could solve the problem by combining the two conitions into one rows(), but I still wonder why chaining rows() doesn't work as I intended.
Rows() methods returns DataTables.Api and it provides the ability to chain according to the reference.
https://datatables.net/reference/type/DataTables.Api
table.rows((index, row, node)=>{return $(node).hasClass("selected") && row[3]<=30}).deselect()
答案1
得分: 0
Short Answer
使用rows({selected:true})
时,确实返回一个API实例(如您所述),但该实例仍然包含所有原始数据,并仅捕获所选行的ID作为额外的元数据。
Longer Answer
假设您使用select extension在数据表中选择了一个或多个行。
然后,您执行以下操作:
table.rows({selected:true})
正如您在问题中所述,并如文档中所述,这将返回:
"带有所选行的DataTables API实例"
但这并不意味着DataTables API现在仅包含那些行。
实际上,这意味着DataTables API包含一些描述所选行集的附加元数据。
所有原始数据(选定和未选定的)仍然存储在该API实例中,并且在执行附加的rows()
调用时仍将使用该数据。
这就是为什么在您的示例链中第一个rows()
调用似乎被忽略的原因 - 因为它实际上被忽略了。
(如果您认为返回的API实例只是原始数据的过滤版本,那么这可能看起来有些反直觉。)
您可以进一步探索这个问题。
我选择了一个不使用选择扩展的演示,以简化问题。但相同的概念也适用:
var dataSet = [
{
"id": "123",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
},
{
"id": "456",
"name": "Donna Snider",
"position": "Customer Support",
"salary": "$112,000",
"start_date": "2011/01/25",
"office": "New York",
"extn": "4226"
},
// ... (其他数据)
];
$(document).ready(function() {
var table = $('#example').DataTable({
data: dataSet,
columns: [
{ title: "ID", data: "id" },
{ title: "Name", data: "name" },
{ title: "Office", data: "office" },
{ title: "Position", data: "position" },
{ title: "Start date", data: "start_date" },
{ title: "Extn.", data: "extn" },
{ title: "Salary", data: "salary" }
]
});
var selected1 = table.rows([1, 2, 3]).data().toArray();
console.log(selected1);
// 预期此操作不会返回数据,但实际上它返回了Tiger Nixon:
var selected2 = table.rows([1, 2, 3]).rows([0]).data().toArray();
console.log(selected2);
// 最初选择行ID的额外元数据:
console.log(table.rows([1, 2, 3])[0]);
});
当我执行以下操作时:
var selected1 = table.rows( [1,2,3] ).data().toArray();
console.log( selected1 );
它如预期地返回了三条记录,分别为Donna、Cedric和Airi,因为它们是行索引为1、2和3的记录。
但当我执行以下操作时:
var selected2 = table.rows( [1,2,3] ).rows( [0] ).data().toArray();
console.log( selected2 );
我期望它不会返回任何数据 - 因为行索引0不包含在行索引1、2或3中。但实际上它返回了Tiger Nixon(原始表中的行索引0)。
您可以查看table.rows( [1,2,3] )
的额外元数据存储在哪里:
console.log( table.rows( [1,2,3] )[0] );
这将返回所选行的DataTables索引值:
[ 1, 2, 3 ]
因此,您确实可以链接API调用;但它们的操作方式可能与您的期望不符,如果您链式调用似乎过滤或缩小了原始数据集。
我无法推测为什么DataTables是以这种方式构建的。您可以在DataTables的论坛上提问,那里可能有比我在这里提供的更好的答案。
英文:
Short Answer
When you use rows({selected:true})
, that does return an API instance (as you note) - but that instance still contains all the original data, and just captures the selected row IDs as additional metadata.
Longer Answer
Let's assume you have selected one or more rows in a DataTable using the select extension.
Then, you execute the following:
table.rows({selected:true})
As you state in the question, and as described in the documentation, this returns a:
> "DataTables API instance with selected rows"
But that does not mean a DataTables API which now contains only those rows.
It actually means a DataTables API with some additional metadata which describes the set of selected rows.
All of the original data (selected and unselected) is still stored in that API instance - and will still be used when you perform an additional chained rows()
call.
That is why it appears as if the first rows()
call in your example chain is ignored - because it effectively is ignored.
(This may appear counter-intuitive if you assume the returned API instance is just a filtered version of the original.)
You can explore this further.
I have chosen a demo which does not use the select extension, for simplicity. But the same concepts apply:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var dataSet = [{
"id": "123",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
},
{
"id": "456",
"name": "Donna Snider",
"position": "Customer Support",
"salary": "$112,000",
"start_date": "2011/01/25",
"office": "New York",
"extn": "4226"
},
{
"id": "567",
"name": "Cedric Kelly",
"position": "Senior Javascript Developer",
"salary": "$433,060",
"start_date": "2012/03/29",
"office": "Edinburgh",
"extn": "6224"
},
{
"id": "632",
"name": "Airi Satou",
"position": "Accountant",
"salary": "$162,700",
"start_date": "2008/11/28",
"office": "Tokyo",
"extn": "5407"
},
{
"id": "987",
"name": "Brielle Williamson",
"position": "Integration Specialist",
"salary": "$372,000",
"start_date": "2012/12/02",
"office": "New York",
"extn": "4804"
}
];
$(document).ready(function() {
var table = $('#example').DataTable({
data: dataSet,
columns: [{
title: "ID",
data: "id"
},
{
title: "Name",
data: "name"
},
{
title: "Office",
data: "office"
},
{
title: "Position",
data: "position"
},
{
title: "Start date",
data: "start_date"
},
{
title: "Extn.",
data: "extn"
},
{
title: "Salary",
data: "salary"
}
]
});
var selected1 = table.rows([1, 2, 3]).data().toArray();
console.log(selected1);
// expect this to find no data, but it finds Tiger Nixon:
var selected2 = table.rows([1, 2, 3]).rows([0]).data().toArray();
console.log(selected2);
// the extra metadata for the initially selected row IDs:
console.log(table.rows([1, 2, 3])[0]);
});
<!-- language: lang-html -->
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="example" class="display dataTable cell-border" style="width:100%">
</table>
</div>
</body>
</html>
<!-- end snippet -->
When I execute the following:
var selected1 = table.rows( [1,2,3] ).data().toArray();
console.log( selected1 );
it returns three records as expected for Donna, Cedric, and Airi, since those are the records with row indexes of 1, 2, and 3.
But when I execute the following:
var selected2 = table.rows( [1,2,3] ).rows( [0] ).data().toArray();
console.log( selected2 );
I would expect it to return no data - because row index zero is not contained in row indexes 1, 2, or 3. Instead I get Tiger Nixon (row index 0 from the original table).
You can see where the extra metadata is stored for table.rows( [1,2,3] )
:
console.log( table.rows( [1,2,3] )[0] );
This returns the DataTables index values of the selected rows:
[ 1, 2, 3 ]
So, yes, you can definitely chain API calls; but how they operate may not be what you expect, if you are chaining calls which appear to filter or narrow down the original data set.
I can't speculate on why DataTables is built this way. You can ask in the DataTables forum for a better answer than I could give you here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论