Статьи

Создание виджета Typeahead с AngularJS

Если вы запускаете проект AngularJS, возможно, вы захотите, чтобы все компоненты были написаны на Angular. Хотя, безусловно, возможно повторное использование существующих плагинов jQuery, добавление jQuery в директиву не всегда является правильным способом сделать что-то. Мой совет — сначала проверить, может ли та же самая вещь быть реализована с помощью чистого Angular более простым / лучшим способом. Это сохраняет код вашего приложения чистым и поддерживаемым. Это руководство, предназначенное для начинающих, поможет читателям создать простой виджет TypeAhead с AngularJS.

обзор

В этом уроке мы собираемся создать простой виджет TypeAhead, который создает предложения, как только кто-то начинает вводить текстовое поле. Мы спроектируем приложение таким образом, чтобы конечный продукт был легко настраиваемым и мог быть легко подключен к существующей системе. Основные этапы процесса создания:

  • Создайте фабрику, которая взаимодействует с RESTful API и возвращает JSON, который будет использоваться для предложений автозаполнения.
  • Создайте директиву, которая будет использовать данные JSON и инкапсулировать поле ввода typeahead.
  • Сохраняйте директиву настраиваемой, чтобы конечные пользователи могли настраивать следующие параметры.

Параметры конфигурации

  1. Точные свойства объекта JSON, которые нужно показать как часть предложений.
  2. Модель в области видимости контроллера, которая будет содержать выбранный элемент.
  3. Функция в области видимости контроллера, которая выполняется при выборе элемента.
  4. Текст-заполнитель (подсказка) для поля ввода typeahead.

Шаг 1: Создание фабрики для получения данных

В качестве первого шага давайте создадим фабрику, которая использует службу $http Angular для взаимодействия с RESTful API. Посмотрите на следующий фрагмент:

 var typeAhead = angular.module('app', []);

typeAhead.factory('dataFactory', function($http) {
  return {
    get: function(url) {
      return $http.get(url).then(function(resp) {
        return resp.data; // success callback returns this
      });
    }
  };
});

Предыдущий код создает фабрику с именем dataFactory Мы не будем вдаваться в подробности фабрики, но нам нужно кратко понять, как работает служба $http Вы передаете URL в функцию get() Другой вызов then()get() Это обещание разрешается возвращаемым значением then() Итак, внутри нашего контроллера мы не взаимодействуем напрямую с $http Вместо этого мы запрашиваем экземпляр factory в контроллере и вызываем его функцию get() Итак, наш код контроллера, который взаимодействует с фабрикой, выглядит следующим образом:

 typeAhead.controller('TypeAheadController', function($scope, dataFactory) { // DI in action
  dataFactory.get('states.json').then(function(data) {
    $scope.items = data;
  });
  $scope.name = ''; // This will hold the selected item
  $scope.onItemSelected = function() { // this gets executed when an item is selected
    console.log('selected=' + $scope.name);
  };
});

В предыдущем коде используется конечная точка API с именем states.json Когда данные будут доступны, мы сохраняем список в items Мы также используем name Наконец, функция onItemSelected()

Шаг 2: Создание Директивы

Давайте начнем с директивы typeahead

 typeAhead.directive('typeahead', function($timeout) {
  return {
    restrict: 'AEC',
    scope: {
      items: '=',
      prompt: '@',
      title: '@',
      subtitle: '@',
      model: '=',
      onSelect: '&'
    },
    link: function(scope, elem, attrs) {
    },
    templateUrl: 'templates/templateurl.html'
  };
});

В директиве мы создаем изолированную область видимости, которая определяет несколько свойств:

  • items
  • prompttypeaheadtitle
  • subtitletitlesubtitletypeAhead Большинство виджетов title Обычно они (если не всегда) имеют два поля для каждой записи в выпадающих предложениях. Если у объекта JSON есть дополнительные свойства, это действует как способ передачи двух свойств, которые будут отображаться в каждом предложении в раскрывающемся списке. В нашем случае subtitlemodel
  • onSelect
  • {
    "name": "Alabama",
    "abbreviation": "AL"
    }

Примечание: пример ответа JSON показан ниже:

 <input type="text" ng-model="model" placeholder="{{prompt}}" ng-keydown="selected=false" />
<br/>

<div class="items" ng-hide="!model.length || selected">
  <div class="item" ng-repeat="item in items | filter:model  track by $index" ng-click="handleSelection(item[title])" style="cursor:pointer" ng-class="{active:isCurrent($index)}" ng-mouseenter="setCurrent($index)">
    <p class="title">{{item[title]}}</p>
    <p class="subtitle">{{item[subtitle]}}</p>
  </div>
</div>

Шаг 3: Создайте шаблон

Теперь давайте создадим шаблон, который будет использоваться директивой.

 prompt

Сначала мы визуализируем текстовое поле ввода, где пользователь будет печатать Приглашение свойства области присваивается атрибуту placeholder Далее мы перебираем список состояний и отображаем nameabbreviation Эти имена свойств настраиваются через свойства области titlesubtitle Директивы ng-mouseenterng-class Далее мы используем filter:model Наконец, мы использовали директиву ng-hide Для свойства selectedtruehandleSelection()false

Шаг 4: Обновите функцию link

Далее, давайте обновим функцию link

 link: function(scope, elem, attrs) {
  scope.handleSelection = function(selectedItem) {
    scope.model = selectedItem;
    scope.current = 0;
    scope.selected = true;
    $timeout(function() {
      scope.onSelect();
    }, 200);
  };
  scope.current = 0;
  scope.selected = true; // hides the list initially
  scope.isCurrent = function(index) {
    return scope.current == index;
  };
  scope.setCurrent = function(index) {
    scope.current = index;
  };
}

Функция handleSelection()model Затем мы сбрасываем currentselected Далее мы вызываем функцию onSelect() Добавлена ​​задержка, потому что назначение scope.model=selecteditem Желательно выполнить функцию обратного вызова области контроллера после обновления модели выбранным элементом. Вот почему мы использовали сервис $timeout

Кроме того, функции isCurrent()setCurrent() Следующий CSS также используется для завершения процесса выделения.

 .active {
  background-color: #C44741;
  color: #f2f2f2;
}

Шаг 5: Настройте и используйте директиву

Наконец, давайте вызовем директиву в HTML, как показано ниже.

 <div class="container" ng-controller="TypeAheadController">
  <h1>TypeAhead Using AngularJS</h1>
  <typeahead items="items" prompt="Start typing a US state" title="name" subtitle="abbreviation" model="name" on-select="onItemSelected()" />
</div>

Вывод

Из этого туториала Вы узнаете, как создать виджет AngularJS TypeAhead с параметрами конфигурации. Полный исходный код доступен для скачивания на GitHub . Не стесняйтесь комментировать, если что-то неясно или вы хотите что-то улучшить. Кроме того, не забудьте проверить живую демонстрацию .