Автозаполнение формы с конкретными условиями

Я работаю с веб-приложением, разработанным с помощью Phoenix Framework (написано на Эликсире).

У меня есть поле формы, которое в настоящее время выглядит так:

<div class="form-group">
  <%= select f, :category_id, @categories, class: "form-control" %>
  <%= error_tag f, :category_id %>
</div>

Это позволяет пользователям выбирать категорию из выпадающего списка (что нормально); тем не менее, я бы хотел, чтобы пользователи видели стандартное текстовое поле, которое будет автоматически заполнять строку, которую вводят, с категориями из моей базы данных, когда они начинают ее вводить.

Функциональность очень похожа на поле «Теги», которое мы используем при публикации вопроса на Stack Overflow.

Как это лучше всего сделать с помощью приложения Phoenix? Я пробовал использовать автозаполнение jQuery; однако мне бы хотелось более «легкое» решение (которое не требует jQuery).

Любые идеи приветствуются. Спасибо за ваше время.


person Andrew Hendrie    schedule 26.04.2016    source источник
comment
Я думаю, что любое решение будет так или иначе использовать JavaScript, поэтому отказ от использования JQuery или какой-либо подобной библиотеки JS оставляет вас с реализацией этого в чистом JS. По моему опыту, это обычно приводит к глючному, неинтуитивному виджету. Вам придется реализовать тривиальные вещи, такие как захват клавиатуры вверх/вниз/клавиши ввода с нуля.   -  person Shovalt    schedule 02.05.2016
comment
Я дал решение с помощью purejavascript, и для доступа к базе данных вы должны просто отправить параметр в dabatase, из которого запросы для подстроки соответствуют столбцу тега.   -  person codefreaK    schedule 03.05.2016


Ответы (2)


Единственное решение, которое я могу придумать, вообще не используя JavaScript, — это список данных. Это отличный новый элемент HTML5, который делает именно то, что вам нужно, но его поддержка браузерами не очень хороша (обновление 2021: в настоящее время поддержка намного лучше).

Если вы хотите избежать JQuery, но по-прежнему можете использовать какой-либо другой виджет JS, вам следует взглянуть на Awesomplete. — сверхлегкий, настраиваемый, простой виджет автозаполнения без каких-либо зависимостей. Если вы включите минимальные файлы JS и CSS, они в сумме составят всего около 8 КБ. Это также смехотворно легко реализовать:

<input class="awesomplete"
       data-list="category1, category2, category3, category4, category5" />

И он может даже прикрепляться к вашему текущему полю выбора (хотя вам придется его скрыть):

<style>
  #mylist { display: none; }
</style>

<div class="form-group">
  <input class="awesomplete" list="mylist" />
  <%= select f, :category_id, @categories, class: "form-control", id: "mylist" %>
  <%= error_tag f, :category_id %>
</div>

Конечно, не забудьте добавить в голову файлы JS и CSS:

<link rel="stylesheet" href="awesomplete.css" />
<script src="awesomplete.min.js" async></script>
person Shovalt    schedule 02.05.2016
comment
Есть ли возможность передать кортеж значений... чтобы при отправке его в phoenix значением был идентификатор, а не имя. Произнесите список данных [{string, int}, {string, int}, {string, int}] - person tblev; 04.08.2021
comment
@tblev из чтения здесь кажется, что параметры метки/значения поддерживается. Это означает, что везде, где вы ранее вводили метку, вы можете использовать / для отделения от фактического значения, которое вы хотите для этой метки. - person Shovalt; 05.08.2021

Решение на чистом ванильном javascript, совместимое со всеми платформами, поддерживающими javascript

  1. В этом подходе текстовое поле прослушивается для нажатия клавиш, и каждый раз, когда происходит событие, вводимый текст сопоставляется с предопределенным набором ввода и, если он найден, добавляется к базовому тегу UL в качестве элементов li.
  2. Здесь css для li берется из того, что отображается в хроме для текстового поля, его можно настроить по своему вкусу.
  3. И что касается получения значений или тегов из части базы данных, это также не проблема, вы можете использовать ajax для получения значений, передавая входные данные в качестве параметра на сторону сервера и возвращая совпавшие теги и добавляя их.

    // variables
    var input = document.querySelector('input');
    var people = ['john doe', 'maria', 'paul', 'george', 'jimmy','Andrew','Hendrie'];
    var results;
    
    // functions
    function autocomplete(val) {
      var people_return = [];
    
      for (i = 0; i < people.length; i++) {
        if (val === people[i].slice(0, val.length)) {
          people_return.push(people[i]);
        }
      }
    
      return people_return;
    }
    
    // events
    input.onkeyup = function(e) {
      input_val = this.value; // updates the variable on each ocurrence
    
      if (input_val.length > 0) {
        var people_to_show = [];
    
        autocomplete_results = document.getElementById("autocomplete-results");
        autocomplete_results.innerHTML = '';
        people_to_show = autocomplete(input_val);
        
        for (i = 0; i < people_to_show.length; i++) {
          autocomplete_results.innerHTML += '<li>' + people_to_show[i] + '</li>';
    
        }
        autocomplete_results.style.display = 'block';
      } else {
        people_to_show = [];
        autocomplete_results.innerHTML = '';
      }
    }
ul{
padding:0;
margin:0;  
}
li{
  max-width:169px;

      padding: 1px 0px;
list-style:none;
      -webkit-appearance: textfield;
    background-color: white;
    border-image-source: initial;
    border-image-slice: initial;
    border-image-width: initial;
    border-image-outset: initial;
    border-image-repeat: initial;
    -webkit-rtl-ordering: logical;
    -webkit-user-select: text;
    cursor: auto;
    padding: 1px;
    border-width: 2px;
    border-style: inset;
    border-color: initial
          text-rendering: auto;
    color: initial;
    letter-spacing: normal;
    word-spacing: normal;
    text-transform: none;
    text-indent: 0px;
    text-shadow: none;

    text-align: start;
    margin: 0em 0em 0em 0em;
    font: 13.3333px Arial;
}
<div id="autocomplete-container">  
  <input type="text" autofocus="true" name="autofocus sample" placeholder="search people" id="autocomplete-input"/>
  <ul id="autocomplete-results">
  </ul>
</div>

OR

Самым простым решением для браузеров, поддерживающих html5, будет список данных.

<input list="browsers">

<datalist id="browsers">
  <option value="Internet Explorer">
  <option value="Firefox">
  <option value="Chrome">
  <option value="Opera">
  <option value="Safari">
</datalist>

http://www.w3schools.com/tags/tag_datalist.asp

РЕДАКТИРОВАТЬ 1

С добавленной навигацией Я забыл изменить изменение текстового поля в отношении навигации, скоро добавлю его

person codefreaK    schedule 03.05.2016
comment
Добавлен текстовый объект, но он глючит jsfiddle.net/o39qrbo0/8 это сбой не виден легко, но если вы двигаетесь вверх и вниз много раз, он появится - person codefreaK; 06.05.2016