20 марта 2011 г.

Применяем autocomlete в Asp.Net MVC

Давайте ка займемся тем, что создадим сегодня базовое приложение, которое будет демонстрировать функцию автозаполнения поля. Функция, скажу я вам, довольно полезная и практичная. Мы вводим в поле несколько новых символов, и нам автоматически предлагаются все варианты с введенными данными. Думаю, что объяснять где и зачем это используется - нет смысла. Поэтому, сразу перейдем к делу.

В реализации нам снова поможет Jquery плагин. Каюсь, но я уже не помню откуда его брал, и как точно он называется, но скачать его можно тут.

Итак, подключим это дело к нашему проекту, заодно создав новый файл productsList.js, в котором будем производить все наши Javascript-действия чтобы не загромождать страницу:

А также в Site.Master:

<script src="/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
    <script src="/Scripts/jquery.autocomplete.js" type="text/javascript"></script>
    <link href="/Content/jquery.autocomplete.css" rel="stylesheet" type="text/css" />

И в нашей странице Products.aspx:

<script src="/Scripts/productsList.js" type="text/javascript"></script>

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


Заполним таблицу тестовыми данными:

Для того, чтобы убедиться в правильности работы плагина, вводим названия продуктов с схожими буквосочетаниями.
Кстати, после создания таблицы, не забудьте перенести ее в модель *dbml-файла.

Перейдем к контроллеру. ActionResult для страницы так и останется пустым:

public ActionResult Products()
        {
            return View();
        }

Кроме этого, создадим метод ProductSel, который будет возвращать в представление данные по Ajax-запросу:

   1:   public ContentResult ProductSel(string q)
   2:          {
   3:              if (Request != null && Request.IsAjaxRequest())
   4:              {
   5:                  String resp = string.Empty;
   6:                  IEnumerable<Product> productsList = m_DataManager.Products.GetAllProducts();
   7:                  foreach (var item in productsList)
   8:                  {
   9:                      if ((item.Name.ToUpper().IndexOf(q.ToUpper()) >= 0))
  10:                      {
  11:                          resp += item.Name + "|" + item.Count + "\n";
  12:                      }
  13:                  }
  14:                  return Content(resp);
  15:              }
  16:              return null;
  17:          }

Метод довольно прост. Сначала мы обращаемся к базе данных, и получаем оттуда список всей продукции в переменную productsList. После этого, перебирая все элементы списка, мы формируем строку ответа, которая будет передана плагину автозапонения. "\n" - разделитель строк, а  "|" - разделитель значений одного параметра.

Теперь к самой странице продукции(Products.aspx). Здесь у нас будет лишь один input для ввода, и span для отображения выбранного значения:

   1:  <input type="text" id="products" name="products" />
   2:      <br />
   3:      <p>
   4:          Selected value:<br />
   5:          <span id="selected"></span>
   6:      </p>

Практически вся магия будет происходить в Javascript-коде страницы, который мы договорились писать в productsList.js:

   1:  $(document).ready(function () {
   2:   
   3:      function liFormat(row, i, num) {
   4:          var result = "Product: " + row[0] + ", count: " + row[1];
   5:          return result;
   6:      }
   7:   
   8:      function selectItem(li) {
   9:          if (li != null) {
  10:              $("#selected").text(li.selectValue);
  11:          }
  12:      }
  13:   
  14:      $("#products").autocomplete(
  15:                  "/home/productsel",
  16:                   {
  17:                       delay: 10,
  18:                       minChars: 2,
  19:                       matchSubset: 1,
  20:                       autoFill: true,
  21:                       maxItemsToShow: 10,
  22:                       lineSeparator: "\n",
  23:                       cacheLength: 10,
  24:                       formatItem: liFormat,
  25:                       onItemSelect: selectItem
  26:   
  27:                   });
  28:  });

Пробежимся немного по всему коду....
При вводе первых символов, подходящие варианты будут отображены под инпутом, в виде обычного списка. Так вот, функция liFormat задает формат отображения одной строки такого списка. row[n] - присланное из контроллера значение параметра. В нашем случае их 2 (название и количество). В методе контроллера они разделены символом "|".
Вторая функция (selectItem) выполняется в момент выбора нами какого-то значения из предложенного списка. Здесь мы просто записываем его в элемент span.
Последняя функция привязывает плагин к нашему полю вводу, задавая ему начальные параметры. Тут мы выполняем запрос к указанному методу контроллера ровно через 10 миллисекунд после ввода второго символа в поле. С остальными параметрами все должны справится т.к. все ясно по их названиям.

Вот и все! Дело сделано!

Смотрим на результат. При вводе в поле второго символа, в фоне происходит ajax-запрос, в результате чего страница получает данные, и предлагает нам варианты, схожие с введенным нами:

А после выбора нужного элемента, его название отдельно выводится под полем ввода:


Все работает. Успешного освоения!
_____
Исходники можно скачать отсюда.