I am trying to match two values of the same object in a multidimensional JSON. First I search for a value in key4 for two input fields which is suggestion featured. After selecting 2 input fields and clicking submit button, I need to check that two input values present in the same set of JSON objects in multi-dimensional JSON (Check for key4 in each JSON object). I mean when searching for Test value 3 and Test value 5 in two input fields, I should get the first element of JSON in below in filter-records element, that is
{
"key1": "Test value 1",
"key3" : [{
"key4" : "Test value 3",
"key5" : "Test value 4"
},
{
"key4" : "Test value 5",
"key5" : "Test value 6"
}]
}
var object = [{
"key1": "Test value 1",
"key3": [{
"key4": "Test value 3",
"key5": "Test value 4"
},
{
"key4": "Test value 5",
"key5": "Test value 6"
}
]
},
{
"key1": "Test value 11",
"key3": [{
"key4": "Test value 13",
"key5": "Test value 14"
},
{
"key4": "Test value 15",
"key5": "Test value 16"
}
]
}
];
const search = document.getElementById("txt-search");
const matchList = document.getElementById("match-list");
searchStates = async searchText => {
const states = object;
let matches = states.filter(state => {
const regex = new RegExp(`^${searchText}`, 'gi');
return state.key3.some(i => i.key4.match(regex)) //(regex);
});
matchList.textContent = JSON.stringify(matches, null, 2)
};
search.addEventListener("keyup", () => searchStates(search.value));
const search2 = document.getElementById("txt-search2");
const matchList2 = document.getElementById("match-list2");
searchStates2 = async searchText2 => {
const states2 = object;
let matches2 = states2.filter(state2 => {
const regex2 = new RegExp(`^${searchText2}`, 'gi');
return state2.key3.some(i => i.key4.match(regex2)) //(regex);
});
matchList2.textContent = JSON.stringify(matches2, null, 2)
};
search2.addEventListener("keyup", () => searchStates2(search2.value));
const search3 = document.getElementById("submit");
const matchList3 = document.getElementById("filter-records");
searchStates3 = async(searchText3, searchText4) => {
const states3 = object;
let matches3 = states3.filter(state3 => {
return state3.key3.some(i => i.key4 == searchText3 && i.key4 == searchText4)
});
matchList3.textContent = JSON.stringify(matches3, null, 2)
};
search3.addEventListener("submit", (evt) => {
evt.preventDefault();
searchStates3(search.value, search2.value)
});
<form role="form">
<div >
<input type="input" id="txt-search" placeholder="Type your search character">
<div id="match-list"></div>
<input type="input" id="txt-search2" placeholder="Type your search character">
<div id="match-list2"></div>
<input type="submit" id="submit" value="submit">
</div>
</form>
<div style="overflow-x:auto;">
<div >
<div>
<div id="filter-records"></div>
</div>
</div>
</div>
In live mode I get JSON from file which I get with the following code const res2 = await fetch('./tt.json');const states2 = await res2.json();. With this code, I get the following error in the console. Uncaught TypeError: Cannot read properties of undefined (reading 'search') and Uncaught SyntaxError: Unexpected token ] in JSON at position 0. How to make it work for two values in a multi-dimension JSON?
CodePudding user response:
Create the functions so that the result of one search can be "fed" as the input (states) of the second search (so, actually, you perform the second search on a state already filtered by the first search). This is more efficient, and the code is much cleaner:
const object = [{
"key1": "Test value 1",
"key3": [{
"key4": "Test value 3",
"key5": "Test value 4"
},
{
"key4": "Test value 5",
"key5": "Test value 6"
}
]
},
{
"key1": "Test value 11",
"key3": [{
"key4": "Test value 13",
"key5": "Test value 14"
},
{
"key4": "Test value 15",
"key5": "Test value 16"
}
]
}
];
const search = document.getElementById("txt-search");
const matchList = document.getElementById("match-list");
const search2 = document.getElementById("txt-search2");
const matchList2 = document.getElementById("match-list2");
const searchStates = ({ search, states }) => {
const regex = new RegExp(`^${search}`, 'gi');
return states.filter(state => state.key3.some(e => e.key4.match(regex)))
}
const updateElTextContent = ({ el, text }) => {
el.textContent = JSON.stringify(text, null, 2)
}
const searchKeyupHandler = (matchListContainer, object) => (value) => {
const matches = searchStates({ search: value, states: object })
updateElTextContent({ el: matchListContainer, text: matches })
}
const input1Handler = searchKeyupHandler(matchList, object)
const input2Handler = searchKeyupHandler(matchList2, object)
search.addEventListener("keyup", (e) => {
input1Handler(e.target.value)
});
search2.addEventListener("keyup", (e) => {
input2Handler(e.target.value)
});
const form = document.getElementById('form')
const matchList3 = document.getElementById("filter-records");
// just feed the result of the first search match to the
// second one - as states
const searchTwoStates = ({ s1, s2, obj }) => {
const match1 = searchStates({ search: s1, states: obj })
const match2 = searchStates({ search: s2, states: match1 })
updateElTextContent({ el: matchList3, text: match2 })
};
form.addEventListener("submit", (evt) => {
evt.preventDefault();
evt.stopPropagation();
searchTwoStates({ s1: search.value, s2: search2.value, obj: object })
});
<form id="form" role="form">
<div >
<input type="input" id="txt-search" placeholder="Type your search character" />
<div id="match-list"></div>
<input type="input" id="txt-search2" placeholder="Type your search character" />
<div id="match-list2"></div>
<input type="submit" id="submit" value="submit" />
<input type="reset" value="reset" />
</div>
</form>
<div style="overflow-x:auto;">
<div >
<div>
<div id="filter-records"></div>
</div>
</div>
</div>
