#14 Main Navigation (Search)
Saturday, January 19, 2019
In this article we will continue the process of setting up our main navigation bar by adding in a search form. In addition to that we will also add the required server side code to take advantage of the search functionality that we added in previous articles.
Parts
- Part 29: Offset Pager Urls
- Part 28: Offset Pager Start
- Part 27: Mock Context Builder
- Part 26: Mock Repository
- Part 25: Mock Async
- Part 24: Picture Tag Helper
- Part 23: Img DPR Tag Helper
- Part 22: Img Responsive Tag Helper
- Part 21: Img Optimized Display
- Part 20: Img Optimization
- Part 19: Img Lazy Loading
- Part 18: Img Responsive
- Part 17: Bottom Nav
- Part 16: Main Nav Cookie
- Part 15: Main Nav Mobile
- Part 14: Main Nav Search
- Part 13: Main Nav Auth
- Part 12: Main Nav Anchors
- Part 11: Main Nav Logo
- Part 10: Search Results
- Part 9: Search Manager
- Part 8: Search Start
- Part 7: Seeding the Database
- Part 6: Domain Database
- Part 5: Emailing Exceptions
- Part 4: Mailkit
- Part 3: View Renderer
- Part 2: Upgrade to 2.1
- Part 1: Quick Start
Search Icon
- WebUi
- Source
- main.page.ts
- Source
Just as we have done previously we are going to include an icon that we can use for our search button (a).
main.page.ts
...
import { faSearch } from "@fortawesome/free-solid-svg-icons/faSearch";
...
library.add(
...
faSearch,
...
);
...
Search form markup
- WebUi
- Pages
- Shared
- _MainNav.cshtml
- Shared
- Pages
Next up is adding the markup for the search form to our main navigation file (b).
_MainNav.cshtml
...
<header>
<nav>
...
<div class="search-bar">
<form action="/search" method="post">
@Html.Raw(antiForgeryToken)
<input type="text" placeholder="Search ExcitonInteractive.com" name="term" aria-label="Search terms input"/>
<button type="submit" aria-label="Search submit button">
<i class="fas fa-search fa-lg"></i>
</button>
</form>
</div>
</nav>
</header>
Styling the search form
- WebUi
- Source
- components
- main-nav
- main-nav.component.scss
- main-nav
- components
- Source
Now that the markup has been added to our page we will turn to adding a little bit of styling to it (c). As I have mentioned before we are going to expand the search form to take up any additional space when we are in a mobile view.
main-nav.component.scss
...
header {
...
.main-navigation {
...
grid-template-areas: "... search ...";
grid-template-columns: ... 1fr ...;
...
@include media-gt($mobile-break-width) {
grid-template-areas: "... search";
grid-template-columns: ... auto;
}
}
...
.search-bar {
grid-area: search;
@include padding(em($gutter) null);
form {
display: flex;
flex-direction: row;
}
input {
margin: 0;
min-width: 0;
border-left-width: 1px;
@include media-gt-or-eq(1440px) {
width: 287px;
}
}
button {
color: $navigation-background-color;
}
}
}
Adding a model to bind the search request to
- WebUi
- Controllers
- Requests
- SearchRequest.cs
- Requests
- Controllers
As we have seen in the markup we will be sending a request to the server that will contain an entry in the form data with the name 'Term'. We could of course just use a string to bind to this in our action method but I prefer to use a class for requests which is what we will use here (d).
SearchRequest.cs
namespace WebUi.Controllers.Requests
{
public class SearchRequest
{
public string Term { get; set; }
}
}
Adding the search endpoint
- WebUi
- Controllers
- SearchController.cs
- Controllers
As it stands now we could easily add a post method to our search page to process a search request. But the way that I prefer to require the structure of the url to be when it comes to pagination eliminates this as a possibility. Instead of just adding a post method to the page we will add a search controller that will take in the request and then redirect the user to the get method of the search page (e).
SearchController.cs
using Microsoft.AspNetCore.Mvc;
using WebUi.Controllers.Requests;
namespace WebUi.Controllers
{
[Route("search")]
public class SearchController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Search([FromForm] SearchRequest request)
{
return RedirectToPage("/Search", new { search = request.Term });
}
}
}