javascript - อัปเดตจำนวนผลลัพธ์ที่ค้นหาและเปลี่ยนการเลือกตามจำนวนครั้งที่ผู้ใช้ค้นหาในอาร์เรย์ของวัตถุ
ฉันอยากเพิ่มฟังก์ชันที่ผู้ใช้สามารถไปยังผลการค้นหาถัดไปได้ ขอบคุณ @ggorlen สำหรับความช่วยเหลือเกี่ยวกับการค้นหาแบบวนซ้ำ
ฉันมีฟังก์ชันการค้นหาแบบเรียกซ้ำที่ให้ค่าตัวแรกและทำให้พวกมัน selected=true และถ้าอยู่ในอาร์เรย์ซ้อนก็ทำให้ showTree=true
ฉันจะเพิ่มฟังก์ชันที่เมื่อผู้ใช้คลิกที่บันทึกการค้นหาถัดไป ตัวเลือก selected: true จะถูกตั้งค่าให้กับผลลัพธ์ถัดไปและลบออกจากผลลัพธ์ก่อนหน้าได้อย่างไร?
และตามผลลัพธ์ใหม่ showTree จะเปลี่ยนไป
วิธีเพิ่มตัวแปรซึ่งได้รับการอัปเดตตามจำนวนครั้งที่มีการเรียกการค้นหา...
ตัวเลือกบันทึกก่อนหน้านี้เพื่อให้ผู้ใช้สามารถย้อนกลับไปยังผลลัพธ์ก่อนหน้า
const expandPath = (nodes, targetLabel) => {
for (const node of nodes) {
if (node.label.includes(targetLabel)) {
return (node.selected = true);
} else if (expandPath(node.item, targetLabel)) {
return (node.showTree = true);
}
}
};
// Output
expandPath(testData, 'ch');
//// add variable for count example: 1 of 25
console.log(testData);
//if user click on nextrecord after search
//nextrecord(){
//logic to remove the selected true from current and add for next
//update showtree
//update recordNumber of totalValue example: 2 of 25
//}
//child3 should get selected true and remove child1 selected true and showtree
//same add showTree= true based on selected value
//if user click on previous record after search
//previousrecord(){
//logic to remove the selected true from current and add for previous
//update showtree
//update recordNumber of totalValue example: 1 of 25
//}
console.log(testData);.as-console-wrapper { max-height: 100% !important; top: 0; }<script>
// Test Data
const testData = [
{
id: 1,
label: 'parent1',
item: [
{
id: 21,
label: 'child1',
item: [
{
id: 211,
label: 'child31',
item: [
{
id: 2111,
label: 'child2211',
item: [{ id: 21111, label: 'child22111' }]
}
]
},
{ id: 222, label: 'child32' }
]
},
{
id: 22,
label: 'child2',
item: [
{
id: 221,
label: 'child421',
item: [{ id: 2211, label: 'child2211' }]
},
{ id: 222, label: 'child222' }
]
}
]
},
{
id: 2,
label: 'parent2',
item: [
{
id: 21,
label: 'child2',
item: [
{
id: 511,
label: 'child51',
item: [
{
id: 5111,
label: 'child5211',
item: [{ id: 51111, label: 'child52111' }]
}
]
},
{ id: 522, label: 'child352' }
]
}
]
}
];
</script>คำตอบ #1
คุณสามารถอ้างอิงรหัสต่อไปนี้
const testData = [
{
id: 1,
label: 'parent1',
item: [
{
id: 21,
label: 'child1',
item: [
{
id: 211,
label: 'child31',
item: [
{
id: 2111,
label: 'child2211',
item: [{ id: 21111, label: 'child22111' }]
}
]
},
{ id: 222, label: 'child32' }
]
},
{
id: 22,
label: 'child2',
item: [
{
id: 221,
label: 'child421',
item: [{ id: 2211, label: 'child2211' }]
},
{ id: 222, label: 'child222' }
]
}
]
},
{
id: 2,
label: 'parent2',
item: [
{
id: 21,
label: 'child2',
item: [
{
id: 511,
label: 'child51',
item: [
{
id: 5111,
label: 'child5211',
item: [{ id: 51111, label: 'child52111' }]
}
]
},
{ id: 522, label: 'child352' }
]
}
]
}
];
// flatten down tree to array and add parent pointer
const flatten = (data) => {
let flattenData = [data]
if (data.item) {
for (const item of data.item) {
item.parent = data;
flattenData = flattenData.concat(flatten(item));
}
}
return flattenData;
}
let flattenData = [];
// flatten down the test data
for (const data of testData) {
flattenData = flattenData.concat(flatten(data));
}
// to update showTree flag
const toggle = (item, expand = true) => {
const parent = item.parent;
if (parent) {
parent.showTree = expand;
if (parent.parent) {
return toggle(parent, expand);
}
return parent;
}
return item;
}
/**
*
* @param {targetLabel} query
* @returns function navigate with param forward flag
*/
const seach = (query) => {
let index = -1;
const items = flattenData.filter(x => x.label.includes(query));
return (forward = true) => {
if (index > -1) {
items[index].selected = false;
toggle(items[index], false);
}
index = index + (forward ? 1 : -1);
let item = null;
if (index > -1 && index < items.length) {
items[index].selected = true;
item = toggle(items[index], true);
}
return {
item,
index,
length: items.length
}
}
}
const navigate = seach('child5211');
// next result
let result = navigate();
// previous result
result = navigate(false);
// result will look like this
/**
* {
* item: root of current item with showTree and selected falgs or null if out of bound,
* index: current match,
* length: total match
* }
*
*/
คำตอบ #2
จัดการทีละเรื่องตรงนี้ คุณสามารถได้ฟังก์ชัน 'ถัดไป' ที่ต้องการได้อย่างรวดเร็วโดยการแปลงการค้นหาแบบเรียกซ้ำของคุณให้เป็นฟังก์ชันตัวสร้าง:
function* expandPath(nodes, targetLabel) {
for (const node of nodes) {
if (node.label.includes(targetLabel)) {
yield (node.selected = true);
} else if (expandPath(node.item, targetLabel)) {
yield (node.showTree = true);
}
}
};
const gen = expandPath(mynodes, "thisTargetLabel");
gen.next()
gen.next() //<-- the next one
มันค่อนข้างยากที่จะตอบคำถามอื่น ๆ โดยไม่รู้บริบทของคุณมากขึ้น แต่สิ่งที่ดูเหมือนว่าคุณต้องการที่นี่คือ state และ class (es6) เป็นวิธีที่ดีในการสร้างสิ่งนี้:
class Searcher {
constructor(mynodes, mylabel){
this.count=0;
this.nodes=mynodes;
this.label=mylabel;
this.generateMatches(this.nodes);
this.selectNode(this.matches[0]); // select the first node
}
generateMatches(nodes){
this.matches=[];
for (const node of nodes) {
if (node.label.includes(this.label)) {
this.matches.push(node);
} else {
this.generateMatches(nodes.node)
}
}
}
updateTreeById(id, node){
this.nodes.forEach(n=>n.showTree = false);
for (const node of this.nodes) {
if (node.id === id) {
//noop but we are here
} else if(this.updateTreeById(id, this.nodes.node)) {
node.showTree = true;
}
}
}
selectNode(i){
const index = i % this.matches.length;
this.currNodeId = this.matches[index].id;
this.matches[index].selected = true // we are wrapping around
this.count = i; // setting your current count
this.updateTreeById(this.matches[index].id)
// update logic, reset trees
}
nextNode(){
this.selectNode(this.count + 1)
}
prevNode(){
this.selectNode(this.count - 1)
}
}
