Главная страница   /   7.4. Создание текстового поля с автозаполнением (ASP.NET MVC 4 в действии

ASP.NET MVC 4 в действии

ASP.NET MVC 4 в действии

Джеффри Палермо

7.4. Создание текстового поля с автозаполнением

Ранее в этой главе мы узнали, как можно использовать Ajax и JSON для отправки запросов на сервер и получения данных. Кроме создания запросов Ajax вручную, можно также использовать клиентские библиотеки элементов управления и jQuery-плагины, которые позволяют абстрагироваться от стандартного кода для работы с запросами Ajax.

jQuery UI (http://jQueryui.com) является одним из таких наборов плагинов. Он построен на ядре jQuery и предоставляет несколько клиентских виджетов пользовательского интерфейса, в том числе «Аккордеон», автозаполнение, кнопки, календарь, диалоговое окно, индикатор выполнения, слайдер и вкладки.

В этом примере мы рассмотрим, как можно использовать плагин Autocomplete для создания списка городов с возможностью поиска, которая похожа на функциональность Google suggest, как на рисунке 7-10.

Рисунок 7-10: Google предлагает варианты, когда вы набираете текст

Создание CitiesController

Для начала мы создадим CitiesController, который будет отображать страницу с текстовым полем, как показано в следующем листинге.

Листинг 7-22: CitiesController
public class CitiesController : Controller
{
	private readonly CityRepository _repository;
	public CitiesController()
	{
		_repository = new CityRepository();
	}
	public ActionResult Index()
	{
		return View();
	}
}

Строка 6: Создает хранилище

CitiesController создает экземпляр CityRepository в своем конструкторе. Это хранилище содержит единственный метод, Find, который принимает элемент поиска и находит все города, названия которых начинаются с указанного элемента. Внутренняя реализация CityRepository не важна для данного примера, но если вы следите за образцами кода для этой главы, вы увидите, что она загружает данные о городах из CSV файла.

Сам класс City представлен в следующем листинге.

Листинг 7-23: Создание класса City
public class City
{
	public int Id { get; set; }
	public string Name { get; set; }
	public string State { get; set; }
	public string DisplayName
	{
		get { return Name + ", " + State; }
	}
}

Объект City представляет собой очень простой POCO (Plain Old CLR Object) - он просто определяет три перезаписываемых свойства (числовой идентификатор, название города и государства, в котором он находится) и одно свойство только для чтения, которое создает удобное для пользователя отображаемое имя.

Действие Index демонстрирует представление, показанное в следующем листинге.

Листинг 7-24: Страница с автозаполнением
<script
	src="@Url.Content("~/Scripts/jquery-1.7.1.js")"
	type="text/javascript"></script>
<script
	src="@Url.Content("~/Scripts/jquery-ui-1.8.16.js")"
	type="text/javascript"></script>
<link
	href="@Url.Content(
		"~/content/themes/base/jquery-ui.css")"
	rel="Stylesheet" type="text/css" />
<script type="text/javascript">
$(function () {
	var autocompleteUrl = '@Url.Action("Find")';
	$("input#city").autocomplete({
		source: autocompleteUrl,
		minLength: 2,
		select: function (event, ui) {
			alert("Selected " + ui.item.label);
		}
	});
});
</script>
<h2>Cities</h2>
<p>
	Start typing a city to see
	the autocomplete behavior in action.
</p>
<p>
	<label for="city">City</label>
	<input type="text" id="city" />
</p>

Строки 1-6: Ссылка на скрипты JQuery

Строки 7-10: Ссылка на стили JQuery UI

Строка 12: Обработчик готового дерева DOM

Строка 13: Создаем URL поиска

Строки 14-19: Добавляем сценарий автозаполения

Строка 30: Контейнер для результатов

Как и в предыдущих примерах, нам необходим jQuery. Если вы не изменяли макет, ссылки на эти сценарии уже включены.

Затем мы добавляем ссылку на стили jQuery UI, которые также включены в шаблон проекта по умолчанию. Опять же, если вы не изменяли макет, они у вас уже есть.

Далее следует блок скрипта, который запускается по окончании загрузки страницы. В первую очередь мы создаем в нем переменную autoCompleteUrl, которая содержит URL-адрес действия Find контроллера CitiesController (который мы еще не создали). Это адрес, который будет запрашиваться каждый раз, когда пользователь вводит символ в поле поиска. Мы затем находим любое текстовое поле на странице с ID city и вызываем плагин Autocomplete на этом элементе. Ему сообщаем адрес, по которому он должен искать данные (в нашем случае autoCompleteUrl), минимальное число символов, которое должно быть введено перед поиском (в нашем случае 2) и функцию обратного вызова, которая должна запускаться после того, как пользователь выбрал результат поиска. Для простоты, мы просто выводим на экран окно alert с названием выбранного города. Наконец, мы определяем текстовое поле, которое позволит пользователю выполнять поиск.

Если мы сейчас запустим страницу, на ней будет отображаться текстовое поле. Однако так как мы еще не создали действие Find, она будет выдавать ошибку, как показано на рисунке 7-11.

Рисунок 7-11: Текстовое поле с автозаполнением отправляет запрос Ajax, когда пользователь вводит поисковый запрос

Когда элемент поиска введен в поле, плагин Autocomplete отправляет запрос Ajax на сервер. В данном случае, он адресован к действию Find и передает ему элемент поиска в виде строкового параметра запроса под названием term. Плагин Autocomplete ожидает, что этот URL вернет массив объектов JSON со следующими свойствами: id, label (ярлык, который будет отображаться в результатах поиска) и value (значение, которое будет вставлено в текстовое поле при нажатии).

На данный момент это вызывает ошибку 404, потому что у нас еще нет действия Find. Давайте создадим его.

Листинг 7-25: Реализация действия Find
public ActionResult Find(string term)
{
	City[] cities = _repository.FindCities(term);
	var projection = from city in cities
		select new
		{
			id = city.Id,
			label = city.DisplayName,
			value = city.DisplayName
		};
	return Json(projection.ToList(),
		JsonRequestBehavior.AllowGet);
}

Строка 3: Поиск города

Строки 4-10: Создаем проекцию результатов

Строки 11-12: Преобразуем данные в JSON

Здесь мы сначала осуществляем поиск всех городов, имена которых начинаются с указанного символа. Затем мы используем LINQ-запрос "в памяти", чтобы сделать проекцию полученных объектов City в коллекцию анонимных типов, которая соответствует структуре JSON и которую ожидает плагин Autocomplete (свойства id, label и value). Наконец мы преобразовываем эти результаты в формат JSON путем вызова метода Json. Как и в примере из листинга 7-13, мы должны явно разрешить передачу данных в формате JSON на запрос GET с помощью поведения AllowGet.

Наконец, когда вы повторно запустите страницу и введете поисковый запрос, вы увидите полученные с сервера результаты, как показано на рисунке 7-12.

Рисунок 7-12: Отображение результатов поиска

Вы также можете наблюдать получение данных JSON с сервера, отслеживая запросы Ajax с помощью Firebug, как показано на рисунке 7-13.

Рисунок 7-13: Получение данных JSON с сервера в ответ на поисковый запрос

Конечная страница позволяет нам выполнить поиск города, введя первые буквы его названия; сервер выполнит поиск и создаст соответствующий объект JSON. Плагин Autocomplete обработает результат и автоматически создаст раскрывающийся список, причем нам не нужно будет писать код для анализа результатов. Наконец, если мы выберем пункт в раскрывающемся списке, свойство value объекта JSON будет вставлено в текстовое поле.