Day 16: Conceptual Organization of the Bootstrap Library

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

There are three main areas of what the Bootstrap people refer to as the infrastructure of the library, and provided you’ve tackled the basics and intent, you should have all you need in those areas of the documentation to markup pages to your heart’s content. Today, we’re just going to look at those areas so you can get a feel on where to hunt for things.

This series is by no means meant to teach you CSS basics or how to modify Bootstrap’s core, rather, it’s about leveraging Bootstrap from MVC. However, there are important bits you should have a feel for, especially if the idea of tinkering with Bootstrap’s internals is up your alley.

The Base CSS

Some HTML elements of the library are just “free”. You get defaults for BODY, background colors, FORMS and form elements without adding any classes. for example.  Others need only simple class assignment, such as styling “lead” copy on a page with the P tag.

Buttons in Bootstrap use classes, which seems odd at first but they work on BUTTON, A and INPUT elements so once you learn the classes this is rather simple to apply.  Each element requires the base “btn” class, and if you want additional coloring you can use one of the contextual classes (active, success, info, warning or danger).

<button type="button" class="btn btn-warning">Warning</button>

There are a number of scenarios where these contextual colors can be applied to backgrounds with tables or paragraphs, and be used for text as well, mostly documented in the helper classes section of the site.  You’ll also find info on using these under component- or element-specific docs, such as with the table.

There is more information on the basics, as well as diving into the code for customization, on the CSS documentation page. If you are familiar with SASS and LESS, or want to trim down pieces of Bootstrap that are not required for your site check out those links as well.

Bootstrap Components

When Bootstrap requires more structure to put things together you’ll be looking to the component documentation. The navbar we looked at yesterday, for example, needs specific containers, classes and arrangements in order for it to render properly.

Dropdowns, button groups, input groups and combinations thereof are all possible with the right markup. Adding things like breadcrumbs, pagination controls, badges and labels with consistent styling has always been a thorn in my side, but they’re made easy with Bootstrap.

You can dig further into these elements and more on the Components page.

Adding Functionality with JavaScript

It’s worth noting that most everything up to this point work without the JavaScript library. However, adding the JS to your site really starts to make Bootstrap sing. (You’ll also need it to handle specific use cases like navbars with collapsed regions.)

One of the things I like most about Bootstrap is that it considers the CSS markup the first-class API, meaning you don’t have to write any JavaScript to make Bootstrap components like modals or tabs work. They’ve pushed this away into their JS file, and allow you to trigger related behaviors with data attributes, like here with the alert. By simply adding a button to your alert element, you get dismiss capabilities for free:

<button type=”button” class=”close” data-dismiss=”alert” aria-hidden=”true”>&times;</button>

The docs JavaScript controls are a little light, and don’t offer much for explanation, but you can learn a fair bit by experimenting with the data attribute classes or using the JS API directly.

Next Steps

Tomorrow is going to be a quick one with a special announcement on some free upcoming training on the MVC Framework and live interaction with experts in the field!

After that, we’ll get back to using these Bootstrap components as something to augment our user experience for applications built with the MVC Framework.

Holy Crap, I Love Windows Live Writer

There’s an old joke in software development that has Jesus and Satan in a coding contest. When the power goes out Satan loses all his code and asks for more time, but God denies his request as his opponent was already done. “Sorry,” says God, “but Jesus saves!”.

I lost over an hour’s work tonight on a couple of posts I’m working on. Thankfully, Writer has my back. I don’t know who that makes me in the coding contest, but check out this recovery folder:

C:\Users_user_name_\AppData\Local\Windows Live Writer\AutoRecover

If Windows Live Writer crashes you can recover most of your work, even if you don’t have autosave enabled. This has got me out of the woods a couple of times.

Happy blogging. Smile

Day 15: Some Bootstrap Basics

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

Through the series so far we’ve started to see what Bootstrap can do, but how does it get there? Why does the default page look like it does? And what are some of these classes we’ve been using?

The Shell That Makes it Tick

Bootstrap is a responsive grid style and JavaScript library that makes some assumptions about the kind of project you’ll be creating:

  • You care about mobile users
  • You want a familiar UX for your users
  • You are targeting clients capable of HTML5, CSS and JavaScript
  • You like the look and feel of Bootstrap, or you: a) know how to change it, or, b) you have a theme you want to use.

People, there are no more excuses for using tables for layout! Unless, of course, you have a table of data you want to display.  You can use the CSS of Bootstrap on it’s own and make use of the built in styles to control the layout of your pages, accommodating for different screen sizes and device resolutions.

JavaScript isn’t a requirement for your site, but anything beyond the basic CSS will need to support it. In some cases, functionality of simple controls is augmented or simply made possible by virtue of the JavaScript library. What does the JS offer?

  • It provides a programmatic API for components and elements of the page
  • It establishes custom events for actions unique to the Bootstrap controls
  • It gives the ability to automatically wire up components on your page – almost akin to “programming” it on the page, but using Data Attributes in your markup.
  • It provides a no-conflict mode to operate with other client-side frameworks
  • It allows components with heavier processing costs to be delay-initiated, making your page look and feel faster

One Grid to…Line Up Them All

Imagine dividing your page up into 12 columns, and using a row to hold those columns, and putting all your rows into a container. Then, you choose if you want to assume a series of “responsive” widths, or a fluid width that is calculated on the fly to control the size of your columns.  In a nutshell, that is what a grid layout system is doing for you.

Check out these samples from the template. Your home page looks like this in a desktop browser on a larger screen resolution:
image

But when you scale it down, you get the following without having to completely design an alternate site:

image

The grid capabilities give you many options for how you want to tackle your layout regardless of the user’s viewport.  This is significant because you don’t have to write your site twice. There was previous emphasis on making a “mobile friendly version” of your site, but the Bootstrap opinion on design is that you should be mobile first. If you’re choosing to build a new site on some greenfield project it is worth spending some time on how the grid breaks down.

The best way to do this is to visit the Grid Template sample site to see how the different arrangements of classes work together.

The MVC Framework’s Home Page

Consider those images above from your project’s home page, and have a look at what’s going on. There is a menu at the top of the page that automatically collapses into a mobile-friendly arrangement when the screen size gets smaller.

image

The code for this navbar control is in the _Layout.cshtml file.

<div class=”navbar navbar-inverse navbar-fixed-top”>
<div class=”container”>
<div class=”navbar-header”>
<button type=”button” class=”navbar-toggle” data-toggle=”collapse” data-target=”.navbar-collapse”>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
<span class=”icon-bar”></span>
</button>
@Html.ActionLink(“Application name”, “Index”, “Home”, new { area = “” }, new { @class = “navbar-brand” })
</div>
<div class=”navbar-collapse collapse”>
<ul class=”nav navbar-nav”>
<li>@Html.ActionLink(“Home”, “Index”, “Home”)</li>
<li>@Html.ActionLink(“About”, “About”, “Home”)</li>
<li>@Html.ActionLink(“Contact”, “Contact”, “Home”)</li>
</ul>
@Html.Partial(“_LoginPartial”)
</div>
</div>
</div>

There are two DIVs inside the inner container, one the header, the second a collapsable section that is displayed on the same row. On smaller screens, that section disappears in favor of the button in the header. The wiring for all this is done with data attributes.

The links in the header are either rendered in that row, or in a mobile-friendly stack of links when the navbar is collapsed. 

See those three spans in there? Those use a class called icon-bar from the Bootstrap library that looks like this:

.navbar-toggle .icon-bar {
display: block;
width: 22px;
height: 2px;
border-radius: 1px;
}

While I’m assuming they could have used an image or something from Glyphicon here, this is a very light-weight way to render the now familiar “hey I got more stuff for you to look at” iconography that many mobile users are accustomed to.

The rest of the content on the page is rendered in Index.cshtml inside the Views\Home folder.

image

There are two parts in play here, a jumbotron component and a row with three equally-sized columns.  The jumbotron is the grey area with the larger title. It assumes the full width of the container it resides in, and gives a few extra style classes to help make content stand out.

<div class=”jumbotron”>
<h1>ASP.NET</h1>
<p class=”lead”>ASP.NET is a free…</p>
<p><a href=”http://asp.net" class=”btn btn-primary btn-lg”>Learn more &raquo;</a></p>
</div>

The three bits of content are basically assembles as follows:

<div class=”row”>
<!– Three of these –>
<div class=”col-md-4”>
<h2>Getting started</h2>
<p>Content…</p>
<p><a class=”btn btn-default” href=”http://…”>Learn more &raquo;</a></p>
</div>
</div>

There are three DIV elements that have the col-md-4 (read: content targeting a minimum of a medium screen resolution and spanning 4 columns). These are all contained in the row DIV, and if they add up to 12 or less (3x4 = 12) then they are almost certain to end up on the same row.

Next Steps

Be sure to punch around with the grid a little and check out the Views\Home\Index.cshtml source in full (above are just the snippets) to get a good grip on how the layout works. Or, try switching the container class on the _Layout to use container-fluid instead. Lots to explore!

We still have a few basic bits and tips to take care of before we return to the mash up of MVC and Bootstrap, so tune in tomorrow where we close those off!

Day 14: Bootstrap Alerts and MVC Framework TempData

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.


This post is dedicated to the memory of my Grandmother, Marianne Chambers, who passed away June 14, 2014 with her two of her daughters at her side. She was a great woman who survived the passing of her husband and the early loss of a son, my father.


Something may go wrong, or it may go right. It may go smooth or go bump in the night. And, at various times, your application will want to let the user know about it. Bootstrap has a component called an Alert that works quite nicely for these types of information.

image

Likewise, the MVC Framework has a great place where we can store these messages without having to worry about postbacks, short term storage or the like. Pairing these two features up makes a great way to relay information to the user.

A Few More Helpers

Add another class file to your project in the Helpers namespace, and drop in the following code:

public class Alert
{
    public const string TempDataKey = "TempDataAlerts";

    public string AlertStyle { get; set; }
    public string Message { get; set; }
    public bool Dismissable { get; set; }
}

public static class AlertStyles
{
    public const string Success = "success";
    public const string Information = "info";
    public const string Warning = "warning";
    public const string Danger = "danger";
}
These classes give us some constants to help render our Bootstrap alerts, as well as a class to help store and pass data around. ## Base Controller – _Almost_ A Best Practice One of the first things you will likely do on any MVC project is to start with a new base controller that you will inherit from instead of the built-in Controller that ships with the framework. While that may seem like a weird suggestion coming from a guy who likes the YAGNI principle, I’ve never worked on a project that didn’t have a base controller, end up with one, or at least couldn’t have used one.  There will be valid cases where you won’t need one, and likely several cases where multiple base controllers will be required, so it’s debatable as to whether or not it should be a rule. This part is a best practice, however: don’t let your base classes get “fat”, loaded with code you’re not using 90% of the time. At any rate, if you choose to use them or not, for this project ours will look like this:
public class BaseController : Controller
{
    public void Success(string message, bool dismissable = false)
    {
        AddAlert(AlertStyles.Success, message, dismissable);
    }

    public void Information(string message, bool dismissable = false)
    {
        AddAlert(AlertStyles.Information, message, dismissable);
    }

    public void Warning(string message, bool dismissable = false)
    {
        AddAlert(AlertStyles.Warning, message, dismissable);
    }

    public void Danger(string message, bool dismissable = false)
    {
        AddAlert(AlertStyles.Danger, message, dismissable);
    }

    private void AddAlert(string alertStyle, string message, bool dismissable)
    {
        var alerts = TempData.ContainsKey(Alert.TempDataKey)
            ? (List<Alert>)TempData[Alert.TempDataKey]
            : new List<Alert>();

        alerts.Add(new Alert
        {
            AlertStyle = alertStyle,
            Message = message,
            Dismissable = dismissable
        });

        TempData[Alert.TempDataKey] = alerts;
    }

}
These methods are going to help us record and render alerts from our controller and into our views.  There are four pretty similar calls going on there that keep the helper strings away from our controllers.  The AddAlert method takes care of fetching or creating a list of alerts. We’re using TempData here for storage which is good for the next _completed_ request from the server to the same client. That could be the current request, should we complete execution and render a view, or that could be the immediately _next_ request, should we decide to redirect the user. Using a list of Alerts gives us the ability to add more than one type of alert, or several instances of alerts to the page at once. If you consider things like ActionFilters (those are coming) that have an opportunity to interact with the execution pipeline, you won’t ever know exactly what parts of your application might be trying to signal something to the user. **Note**: I got the idea for this approach through working with [Eric Hexter](https://twitter.com/ehexter) on the [Twitter.Bootstrap.Mvc](https://github.com/erichexter/twitter.bootstrap.mvc) project. In that version, Eric’s implementation allowed for one message per alert type, but it was definitely what got the ball rolling for me on this one. ## Updates to PersonController Start by changing the declaration to inherit from our spanky new base class.
public class PersonController : BaseController
Then, update your create method to use the new methods we’ve added.
[HttpPost]
public ActionResult Create(Person person)
{
    if (ModelState.IsValid)
    {
        _people.Add(person);
        Success(string.Format("<b>{0}</b> was successfully added to the database.", person.FirstName), true);
        return RedirectToAction("Index");
    }
    Danger("Looks like something went wrong. Please check your form.");
    return View(person);
}

We’ve made it super easy to store various alerts which will hang around in memory until we complete a request. In the case of the happy path above, the Success message hangs around on the server until the client requests the redirected content.  For the Danger message on the sad path, the view is immediately returned and the TempData is cleared.

Showing our Alerts

While we could just put all the info we need into the layout, we can keep our code cleaner by using a partial view to render the alerts. Under Views\Shared, add a new partial view called _Alerts.cshtml and put in the following code:

@{
var alerts = TempData.ContainsKey(Alert.TempDataKey)
? (List<Alert>)TempData[Alert.TempDataKey]
: new List<Alert>();

<span class="kwrd">if</span> (alerts.Any())
{
    &lt;hr/&gt;
}

<span class="kwrd">foreach</span> (var alert <span class="kwrd">in</span> alerts)
{
    var dismissableClass = alert.Dismissable ? <span class="str">"alert-dismissable"</span> : <span class="kwrd">null</span>;
    &lt;div <span class="kwrd">class</span>=<span class="str">"alert alert-@alert.AlertStyle @dismissableClass"</span>&gt;
        @<span class="kwrd">if</span> (alert.Dismissable)
        {
            &lt;button type=<span class="str">"button"</span> <span class="kwrd">class</span>=<span class="str">"close"</span> data-dismiss=<span class="str">"alert"</span> aria-hidden=<span class="str">"true"</span>&gt;&amp;times;&lt;/button&gt;
        }
        @Html.Raw(alert.Message)
    &lt;/div&gt;
}

}

We grab the alerts out of the TempData (if they exist) and then loop through each one, rendering them in the order they were added. If they had the dismissable flag set to true, we also render the appropriate Bootstrap elements and styles to make the alert go away on command.

Now update your _Layout.cshtml to include the call to render the partial view. Your container with the call to RenderBody() should now look like this:

<div class=“container body-content”>
@{ Html.RenderPartial(“_Alerts”); }
@RenderBody()
<hr />
<footer>
<p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>

And now, after you add a new person to the list, you’ll see a nicely formatted, dismissable alert at the top of the page.

image

Next Steps

We’ve been jumping around a bit and starting to form a few ideas about how the Asp.Net MVC Framework and Bootstrap can work together, but perhaps it’s time to look at a few of the basics that are already in use with the default template.

Day 13: Standard Styling and Horizontal Forms

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

With yesterday having a quick look at the inline styling for a search form, it’s only appropriate to have a look at the other types of styling as well. Users are going to want to enter data!

We’re going to make a quick pit stop first to update our Person class so that we can take advantage of a few of the validation features of both MVC and the Bootstrap library.

For you 15-minutes-or-less folks out there, sorry…this is one of the longer posts, but we’re covering a lot of useful ground!

Updating our Person Model (Class) in Person.cs

We’re going to need to do two things here, add a constructor (so we don’t run into problems with our collection) and make all fields except PersonId and Skills required. The Person class should look like this when you’re done:

public class Person
{
public Person()
{
Skills = new HashSet<string>();
BirthDate = DateTime.Now.AddYears(-20);
}

<span class="kwrd">public</span> <span class="kwrd">int</span> PersonId { get; set; }

[Required]
<span class="kwrd">public</span> <span class="kwrd">string</span> FirstName { get; set; }

[Required]
<span class="kwrd">public</span> <span class="kwrd">string</span> LastName { get; set; }

[Required]
<span class="kwrd">public</span> DateTime BirthDate { get; set; }

[Required]
[UIHint(<span class="str">"BooleanButtonLabel"</span>)]
<span class="kwrd">public</span> <span class="kwrd">bool</span> LikesMusic { get; set; }

[Required]
[EmailAddress]
<span class="kwrd">public</span> <span class="kwrd">string</span> EmailAddress { get; set; }

<span class="kwrd">public</span> ICollection&lt;<span class="kwrd">string</span>&gt; Skills { get; set; }

}

Note that on the EmailAddress, we also added an attribute called, well, EmailAddress. This is a pre-defined validation attribute that the Framework uses to give us useful information in our controller, as well as to leverage client-side scripts for validation (to save round-tripping). Best of both worlds!

Allowing Create on Our Controller

Now we can pop into our controller and set things up for the create action. We’ll need two methods – one for the GET and one for the POST. The GET method creates a default Person object and passes it to the view.

public ActionResult Create()
{
var person = new Person();
return View(person);
}

The POST method is decorated with an attribute and accepts an instance of Person back as a parameter. This is one of the really great features of the MVC Framework: while you still have access to the form collection and full request object, you don’t have to deal with the cruft unless you want or need to; the Framework performs “model binding” for you and fills in the properties of the parameter objects you are expecting based on the names of the fields passed in.

[HttpPost]
public ActionResult Create(Person person)
{
if (ModelState.IsValid)
{
_people.Add(person);
return RedirectToAction(“Index”);
}

<span class="kwrd">return</span> View(person);

}

The base Controller class that we inherit from also gives us some rich capabilities for evaluating the incoming parameter. We can inspect some simple pre-checked values, add validation error messages and deal with the user input as we see fit.

We are able to check ModelState.IsValid because we setup our model to require certain fields. You can add all kinds of validations to cover min and max values, ranges, matches based on Regexes, or, as we did, a check to make sure an Email address is valid. There are more still, and you can create your own if you like.

Generating the View

Now, you’ve done this before but we’re going to approach it a little differently today. This time, when you right-click on the Create method in the controller, be sure to select the correct template and options.

image

It’s a Create template, with the Person class as the model. You’ll want to clear the partial checkbox if it’s selected and make sure you “Include Script Libraries”.  Remember that leaving the name of the view as Create allows the framework to pick it up on it’s own.

This One’s Not Quite Free

The default view actually looks pretty good, in fact, you’d have to remove the form-horizontal style from the class attribute of the div (in the root of the form that is generated) to get the “standard” look-and-feel, which would be like this:

image

But you’ll notice that we’re missing something in particular: a way to add skills to our person. Also, it looks way better with that form-horizontal in there!

Getting Things Straight

So, if you removed that form-horizontal, add it back. Then we’re going to add the next little bit of markup, right before the submit button on the form:

<div class=”form-group”>
@Html.LabelFor(model => model.Skills, htmlAttributes: new { @class = “control-label col-md-2” })
<div class=”col-md-10”>
<div class=”input-group”>
<span class=”input-group-btn”>
<button class=”btn btn-default” id=”add-skill” type=”button”>
<span class=”glyphicon glyphicon-plus”></span>
</button>
</span>
<input type=”text” id=”skill” class=”form-control” placeholder=”Type, then click + to add” />
</div>
</div>
</div>

<div id=”skills-wrapper”></div>

<div class=”form-group”>
<div class=”col-md-offset-2 col-md-10”>
<ul id=”skills-list” class=”list-group”></ul>
</div>
</div>

You’ll notice that we don’t actually have any new form elements here that will submit with the form (the input there doesn’t have a name and won’t appear in the submitted form collection), but we have a textbox that lets you enter some text.

image

There is an empty DIV there that we’ll use to add hidden text inputs to the form via jQuery. We also have a styled UL list in there that we’ll use to display what has already been added.

We’ll add the following script to make that markup tick, which you can add at the bottom of the scaffolded script section in Create.cshtml:

<script>
$(function () {
$(“#add-skill”).click(function () {
// get the value of the added skill
var skill = $(“#skill”).val();

        <span class="rem">// push hidden input to our form</span>
        $(<span class="str">"#skills-wrapper"</span>).append($(<span class="str">"&lt;input type='hidden' name='Skills' value='"</span> + skill + <span class="str">"' /&gt;"</span>));

        <span class="rem">// add list item for display purposes</span>
        $(<span class="str">"#skills-list"</span>).append($(<span class="str">"&lt;li class='list-group-item'&gt;"</span> + skill + <span class="str">"&lt;/li&gt;"</span>));

        <span class="rem">// reset the form</span>
        $(<span class="str">"#skill"</span>).val(<span class="str">""</span>).focus();
    });
});

</script>

The comments in the script lay out the goal here, essentially that we’re going to grab the value from the entry box and turn it into both a hidden form element and an LI in that unordered list we created earlier. Finally, we reset the input and set the focus.

Here it is in action!

image

I Really Like This Part

Remember how we didn’t add any form elements with the name “Skills”? Well, we did in our JavaScript. In fact, we’ll add as many hidden form elements with the same name, “Skills”, to the form as the user would like. What happens to those form elements with the same name?

In your controller, in the POST method you added, set a breakpoint anywhere in the code, then navigate to your Create page and fill out the form. When you submit, you’ll be able to inspect the Skills property of the person…the MVC Framework model binding is smart enough to see multiple instances of the same-named form element (in our case, a hidden text element) that has the name of a property in our model.

It news up a collection for us and populates it with the values. Sweet!

Next Steps

While the form is now submitting and you can see any person you add in the collection, you wouldn’t know it unless you scrolled down on your index. Tomorrow we’ll add some more visibility into what is going on with Bootstrap alerts, assisted by a new base class for our controller and TempData.

Day 12: Implement Search Using Inline Forms and AJAX

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

It had to happen; at some point we were going to need to let our users enter some data! Well, that time has come, so let’s start by adding a handy-dandy search form to our Person page.

Forms will need a few cues on how to properly render themselves and take part in Booststrap’s style party of awesome. Let’s get a search form going and start filtering our results.

There are actually a few styles of forms that you can get going. A standard styling gives you label-over-control type layout, horizontal forms give you label-beside-control layout and inline styling gives you controls without labels side-by-each continuously in the row. That’s the one we’ll go with to generate our simple search form:

image

Create a partial view under the Views\Person folder. You can make it an empty one, and call it _PersonSearchForm.cshtml.  Paste in the following code:

<hr/>
<div class=”container”>
<div class=”pull-right”>
<form class=”form-inline” role=”form”>
<div class=”form-group”>
<label class=”sr-only” for=”search-text”>Email address</label>
<input type=”text” class=”form-control” id=”search-text” placeholder=”Enter Search Text”>
</div>
<button type=”button” class=”btn btn-success” id=”search-btn”>Search</button>
</form>
</div>
</div>

We have a few things going on here:

  • The HR tag is just a style thing and not required. It makes the search form look more “balanced” vertically on the form.
  • There is a DIV that acts as a container, keeping our content separate from the rest of the page. It is a wrapper for a “pull-right” styled DIV that moves our search bar over to the right hand side of the page.
  • The form is given a class of “form-inline”. This is the first important part of making our controls and labels show up correctly.
  • Inside that FORM element we have a DIV with a class of “form-group”. This lets Bootstrap know (or rather, the browser through Bootstrap’s CSS) that these controls are related in some way. Specifically, we have a label for an input.
  • Because this is an “inline” form, we’re using the “sr-only” class on the label to eat the display and keep the visuals tidy. “SR” stands for “Screen Reader”; this is an accessibility tag.

When the form data comes calling, we’re going to need someone to answer the phone on the controller side.

The Controller’s Search Method

In your PersonController class, add the following public method:

public ActionResult SearchPeople(string searchText)
{
var term = searchText.ToLower();
var result = _people
.Where(p =>
p.FirstName.ToLower().Contains(term) ||
p.LastName.ToLower().Contains(term)
);

<span class="kwrd">return</span> PartialView(<span class="str">"_SearchPeople"</span>, result);

}

This accepts a string parameter and finds any matches where FirstName or LastName match what the user entered, then it returns via a call to PartialView to generate the result. We’re using a partial because we don’t want to have to reload the entire page each time the user clicks the search button.

A quick note: the astute reader will note that that this simplified method of search won’t pass the Turkey Test. If you work with different cultures, this is a great side-read, and you’ll need to approach the problem in a different way.

Later in the series we’ll cover best practices around accessing and filtering data, but this approach will suffice for now, using the local static collection of data that we built yesterday.

When we call PartialView the MVC Framework doesn’t attempt to resolve a layout, so we just get the meat that lives in the cshtml file itself and as processed by the view engine. Rendered via the controller, we have to pass in our data as a parameter. If you were rendering a partial via a View (with an HtmlHelper) the partial could ‘inherit’ the parent page’s model and use that to render your content. The partial we need should be located in Views\Person\ and called _SearchPeople.cshtml and the code looks like the following:

@model IEnumerable<SimpleSite.Models.Person>

@Html.DisplayForModel(Model)

@if (!Model.Any())
{
<h3>Sorry!</h3>
<p>Looks like there’s no results for that person.</p>
}

Partial in place, controller set up to search…off to the core view.

Updating the View

Back in Views\Person\Index.cshtml there isn’t a lot we have to do to get our form to display. Update the code so it reads as follows:

@model IEnumerable<SimpleSite.Models.Person>

@{ Html.RenderPartial(“_PersonSearchForm”); }

<div id=”people-data”>
@Html.DisplayForModel(Model)
</div>

I have updated the view from yesterday by wrapping the data with a DIV that acts as a container. We’ll use that later when we AJAX up the page. Press CTRL+F5 to see the updated view in action.

image

This handles the display aspect, but we need some script in place to handle the button click and make the AJAX call, finally updating the page with the search results. Add a script section to the bottom of the page as follows:

@section scripts
{
<script type=”text/javascript”>
$(function () {
// it’s lonely here…
});
</script>
}

Today’s Bonus Content: Sections are defined in the layout page that is used by your view. You can find them in Views\Shared_Layout.cshtml. These sections can be required or optional per your needs. The default template defines only the scripts section, but you may often wish to include something in the page header or footer. Oooo! Sounds like another blog post!

Now the script doesn’t do anything quite yet, except give us a place to land. What you see above is called a “self-executing anonymous method”, which is a good term to know if you want to sound smart around your boss. Basically, jQuery will make sure any code in this block is executed in a cross-browser friendly way after the page is finished loading.

Replace that lonely comment with the following code:

$(“#search-btn”).click(function () {
var searchTerm = $(“#search-text”).val();
$.get(“SearchPeople”, { searchText: searchTerm })
.success(function(data) {
$(“#people-data”).html(data);
});
});

If you’re not familiar with JavaScript or the patterns that jQuery uses, here’s little breakdown of what is happening:

  • A click event handler is setup for the element in the DOM that has an ID of “search-btn”.
  • The event handler is an anonymous method that invokes the jQuery get() method, passing in the action that we’re targeting and the data that we’re trying to pass in.
  • The data we’re passing in is read from the form and assigned to the searchText key
  • When you pass in parameters from calls like this, you need to make sure spelling and case are identical to avoid rapid hair loss. And null values.
  • The get() method follows the “promise” pattern, and you get to register a callback when the search is completed. Here, we use the success callback.
  • Our anonymous callback is invoked when the AJAX completes successfully and it updates the data container (“people-data”) with the HTML that is returned from our controller.

Try typing in some search terms from your Person\Index page.

image

Bazinga!

Next Steps

Our search form looks fine but wouldn’t be ideal for data entry. Tomorrow we’ll look at the other two variants of forms and wire up a view (and our controller) to allow users to create new people.