Hi!
I am building a search function for a website and created a route, that returns a fully built html table with the results which is then fetched as soon as the user is typing into the search field. It works almost as expected, but of course I cannot use regular spaces in the search string, as it needs to work as a URL for the route. I then replaced every space in the input string with “%space%” and used str_replace in the route to change it back to a space.
However now whenever I search and use a space it results in posts that contain any one of the words when I expected it to only show when all words fit the post. So it adds other projects as soon as I use a space. As if they were separate search terms.
Example with only one word only shows one project:
Example with two words shows two projects
For the search I of course need a different behaviour. How can I achieve that it only shows projects that contain all of the separate words that were typed?
This is what my route looks like:
[
'pattern' => '/search/(:any)',
'action' => function ($any) use ($kirby) {
$searchTerm = str_replace('%space%', ' ', $any);
$results = $kirby->site()->search($searchTerm, 'title|name', ['words' => true]);
$html = "<table class='index-table search-results-table'>";
$html .= "<thead><tr><th>Name</th><th>Titel</th></tr></thead>";
$arr = [];
foreach($results as $result) {
$html .= "<tr><th>" . $result->name() . "</th><th>" . $result->title() . "</th></tr>";
}
$html .= "</table>";
return $html;
}
]
and on the frontend:
searchField.addEventListener('input', (input) => {
(async () => {
const results = await fetchSearchResults(searchField);
searchContainer.innerHTML = results;
})()
});
async function fetchSearchResults(searchField) {
const searchTerm = searchField.value;
const cleanSearchTerm = searchTerm.replace(' ', "%space%");
const response = await fetch(`/search/${cleanSearchTerm}`);
const searchResults = await response.text();
return searchResults;
}