I'm trying to create a search bar that adds a query parameter when submitted.
Answered
berkserbet posted this in #help-forum
I'm a newby so I assume I am missing something here. I have a search bar and submit button created. I just can't figure out the query param part. It should be something OnSubmit, but I haven't been able to get anywhere.
'use client';
import React from 'react'
interface Company {
rank: number;
name: string;
total: number;
applicationStage: number;
postInterview: number;
}
interface Props {
search: string;
companies: Company[];
}
const CompanyTable = ({ search, companies }: Props) => {
const searchFilter = (companies: Company[]) => {
if (!search) { return companies } else { return companies.filter(el => el.name.toLowerCase().includes(search.toLowerCase()))} }
const filtered = searchFilter(companies)
return (
<>
<form className='flex justify-center'>
<input className='border border-gray-400 rounded-md p-2 m-2' placeholder='Search' value={search}/>
<button className='border border-gray-400 rounded-md p-2 m-2' type='submit'>Search</button> {/* I want to use the text input and add a query param */}
</form>
<table className='table table-zebra table-pin-rows'>
<thead>
<tr>
<th>Rank</th>
<th>Name</th>
<th>Total Reports</th>
<th>Application Stage</th>
<th>Post Interview</th>
</tr>
</thead>
<tbody>
{filtered.map((company: Company) => (<tr className="hover" key={company.rank}>
<td className='w-0 text-center'>{company.rank}</td>
<td>{company.name}</td>
<td className='w-0 text-center'>{company.total}</td>
<td className='w-0 text-center'>{company.applicationStage}</td>
<td className='w-0 text-center'>{company.postInterview}</td>
</tr>))}
</tbody>
</table>
</>
)
}
export default CompanyTableAnswered by Wuchang bream
'use client'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useState } from 'react'
const SearchContainer = () => {
// NextJs Navigation
const router = useRouter()
const searchParams = useSearchParams()
const pathname = usePathname()
// React States
const [search, setSearch] = useState(searchParams.get('search') || '')
// Handle Submitting
const handleSubmit = (e) => {
e.preventDefault()
router.push(`${pathname}/?search=${search}`)
}
return (
<form className='flex justify-center'>
<input className='border border-gray-400 rounded-md p-2 m-2' placeholder='Search' onChange={(e) => setSearch(e.target.value)} defaultValue={search}/>
<button className='border border-gray-400 rounded-md p-2 m-2' type='submit' onClick={handleSubmit}>Search</button> {/* I want to use the text input and add a query param */}
</form>
)
}
export default SearchContainer9 Replies
Wuchang bream
You use to be able to set search params, but now I believe you can just get search params with useSearchParams. This is what I came up with to add search params. Import useRouter from next/navigation and assign it to router.
Then to call to it, do changeRoute({ search: value }). To remove a param, just pass it undefined as the value.
// Change Search Params
const changeRoute = (newParams) => {
const params = new URLSearchParams(searchParams)
for (const property in newParams) {
if (newParams[property] === undefined) params.delete(property)
else params.set(property, newParams[property])
}
router.replace(pathname + '?' + params.toString(), { scroll: false })
}Then to call to it, do changeRoute({ search: value }). To remove a param, just pass it undefined as the value.
@Wuchang bream You use to be able to set search params, but now I believe you can just get search params with useSearchParams. This is what I came up with to add search params. Import useRouter from next/navigation and assign it to router.
// Change Search Params
const changeRoute = (newParams) => {
const params = new URLSearchParams(searchParams)
for (const property in newParams) {
if (newParams[property] === undefined) params.delete(property)
else params.set(property, newParams[property])
}
router.replace(pathname + '?' + params.toString(), { scroll: false })
}
Then to call to it, do changeRoute({ search: value }). To remove a param, just pass it undefined as the value.
Thank you, I will try to figure that out. Is there no way to do it like this example:
I would need the button to be the link and the search field to populate based on the inputted text
<Link href="/?search=bbb">BBB</Link>I would need the button to be the link and the search field to populate based on the inputted text
@berkserbet Thank you, I will try to figure that out. Is there no way to do it like this example:
`<Link href="/?search=bbb">BBB</Link>`
I would need the button to be the link and the search field to populate based on the inputted text
Wuchang bream
You could do this as well:
If needed, you could also do router.replace to not track it in your history.
const router = useRouter()
const handleSubmit = (value) => {
router.push(`/?search=${value}`)
}If needed, you could also do router.replace to not track it in your history.
So rather than using Link, you would have a submit button and pass the value to handleSubmit, whether throug a useState or another method.
@Wuchang bream You could do this as well:
const router = useRouter()
const handleSubmit = (value) => {
router.push(`/?search=${value}`)
}
If needed, you could also do router.replace to not track it in your history.
That makes sense - I'm not quite sure how to do the part where I grab the value and run the handleSubmit command. Would you be able to show me on this code:
<form className='flex justify-center'>
<input className='border border-gray-400 rounded-md p-2 m-2' placeholder='Search' value={search}/>
<button className='border border-gray-400 rounded-md p-2 m-2' type='submit'>Search</button> {/* I want to use the text input and add a query param */}
</form>This is what I tried, but nothing happened (handleSubmit worked great on it's own)
<form className='flex justify-center' onSubmit={(e) => {handleSubmit('test')}}>
<input className='border border-gray-400 rounded-md p-2 m-2' placeholder='Search' value={search}/>
<button className='border border-gray-400 rounded-md p-2 m-2' type='submit'>Search</button> {/* I want to use the text input and add a query param */}
</form>Wuchang bream
'use client'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useState } from 'react'
const SearchContainer = () => {
// NextJs Navigation
const router = useRouter()
const searchParams = useSearchParams()
const pathname = usePathname()
// React States
const [search, setSearch] = useState(searchParams.get('search') || '')
// Handle Submitting
const handleSubmit = (e) => {
e.preventDefault()
router.push(`${pathname}/?search=${search}`)
}
return (
<form className='flex justify-center'>
<input className='border border-gray-400 rounded-md p-2 m-2' placeholder='Search' onChange={(e) => setSearch(e.target.value)} defaultValue={search}/>
<button className='border border-gray-400 rounded-md p-2 m-2' type='submit' onClick={handleSubmit}>Search</button> {/* I want to use the text input and add a query param */}
</form>
)
}
export default SearchContainerAnswer
Wuchang bream
I forgot to include usePathname earlier. This works to update the query. Then use a useEffect to run every time searchParams.get('search') changes if you need to run code in the same component when it updates.
Worked, thanks!