Подтвердить что ты не робот

Как настроить автозаполнение jquery-ui в Rails

Мне нужна помощь в том, как реализовать jquery-ui autocomplete в моем приложении Rails.

Я хочу добавить автозаполнение в текстовое поле, где пользователь может ввести имя клиента. Поскольку могут быть сотни клиентов, мне нужно будет вывести предлагаемые значения автозаполнения "удаленно", как в таблице, (по крайней мере, это то, что я понимаю).

Основная проблема, которую я не понимаю, заключается в том, как предоставить предлагаемые значения в текстовом поле автозаполнения. Я прочитал jquery-ui docs, но я, кажется, немного плотный в этом вопросе.

Итак, что я действительно делаю, это пример того, как я могу заставить это работать в приложении Rails, не обязательно полное описание того, как создается javascript (что команда jquery-ui сделала для меня =)).

Например, как я могу подготовить данные для автозаполнения и как добавить функцию автозаполнения в текстовое поле.

4b9b3361

Ответ 1

Ну, я так и не получил ответа на мой вопрос, поэтому мне пришлось разобраться в этом. Я думал, что должен опубликовать решение, которое я придумал, если есть другие ребята, которые задаются вопросом о том же.

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

Я думаю, что лучший способ показать это на примере. Итак, вот как я получил виджет автозаполнения для работы в моем приложении. Вы можете пойти дальше и поместить следующий код в свое приложение, даже если вы не понимаете, что происходит, тогда мы можем пересмотреть, как каждая часть работает на примере. После этого вы должны понять, как изменить его для вашего использования или преломлять его.


ВКЛЮЧИТЬ JQUERY UI В ВАШИХ РАЙОНАХ APP.

Загрузите копию jQuery UI и разместите jquery-ui-1.8.2.custom.min.js внутри вашего каталога /public/javascript. Также убедитесь, что у вас есть копия самого jQuery и что она также находится в той же папке.

Включите файл пользовательского интерфейса jQuery и файл jQuery в ваш файл application.html.erb, как это.
(вы можете назвать файлы по своему усмотрению, если они совпадают)

<%= javascript_include_tag 'jquery.min', 'jquery-ui-1.8.2.custom.min.js' %>

В вашей загрузке пользовательского интерфейса jQuery у вас будет папка, содержащая все ваши данные CSS. Название будет меняться в зависимости от выбранной вами темы, например, я выбрал тему " cupertino". Поместите всю папку, содержащую ваши данные CSS, в /public/stylesheets/. Затем включите файл CSS в свой файл application.html.erb следующим образом.

<%= stylesheet_link_tag 'cupertino/jquery-ui-1.8.2.custom' %>


ПРИМЕР AUTOCOMPLETE JAVASCRIPT

Теперь возьмите следующий фрагмент кода и поместите его в один из ваших " новых" представлений. Вы можете использовать это в любом представлении, но поймите, что я буквально взял его из существующего представления, принадлежащего контроллеру под названием "links_controller", и он вытаскивает данные из "people_controller". Надеюсь, вы знаете достаточно о Rails, чтобы понять, что вам нужно изменить, чтобы это сработало для вас.

- Начните большую часть кода -

    <script type="text/javascript">
    $(function() {

 // Below is the name of the textfield that will be autocomplete    
    $('#select_origin').autocomplete({
 // This shows the min length of charcters that must be typed before the autocomplete looks for a match.
            minLength: 2,
 // This is the source of the auocomplete suggestions. In this case a list of names from the people controller, in JSON format.
            source: '<%= people_path(:json) %>',
  // This updates the textfield when you move the updown the suggestions list, with your keyboard. In our case it will reflect the same value that you see in the suggestions which is the person.given_name.
            focus: function(event, ui) {
                $('#select_origin').val(ui.item.person.given_name);
                return false;
            },
 // Once a value in the drop down list is selected, do the following:
            select: function(event, ui) {
 // place the person.given_name value into the textfield called 'select_origin'...
                $('#select_origin').val(ui.item.person.given_name);
 // and place the person.id into the hidden textfield called 'link_origin_id'. 
        $('#link_origin_id').val(ui.item.person.id);
                return false;
            }
        })
 // The below code is straight from the jQuery example. It formats what data is displayed in the dropdown box, and can be customized.
        .data( "autocomplete" )._renderItem = function( ul, item ) {
            return $( "<li></li>" )
                .data( "item.autocomplete", item )
 // For now which just want to show the person.given_name in the list.
                .append( "<a>" + item.person.given_name + "</a>" )
                .appendTo( ul );
        };
    });
    </script>



<h1>New link</h1>

<% form_for(@link) do |f| %>
  <%= f.error_messages %>

<!-- Place the following text fields in your form, the names are not important. What is important is that they match the names in your javascript above -->
  <p>
        Select which person you want to link:<br /> 
<!-- This is the textfield that will autocomplete. What is displayed here is for the user to see but the data will not go anywhere -->
        <input id="select_origin"/>
<!-- This is the hidden textfield that will be given the Persons ID based on who is selected. This value will be sent as a parameter -->
      <input id="link_origin_id" name="link[origin_id]" type="hidden"/>
  </p>
<!-- end of notes -->
  <p>
    <%= f.label :rcvd_id %><br />
    <%= f.text_field :rcvd_id %>
  </p>
  <p>
    <%= f.label :link_type %><br />
    <%= f.text_field :link_type %>
  </p>
  <p>
    <%= f.label :summary %><br />
    <%= f.text_area :summary %>
  </p>
  <p>
    <%= f.label :active %><br />
    <%= f.check_box :active %>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

- Конец большого фрагмента кода -

Теперь соедините точки.


ПРЕДОСТАВЛЯТЬ ДАННЫЕ ДЛЯ AUTOCOMPLETE ДЛЯ ИСПОЛЬЗОВАНИЯ КАК ПРЕДЛОЖЕНИЯ

Давайте начнем с подключения некоторых данных, которые текстовое поле автозаполнения может отображать в раскрывающихся предложениях. Формат, который мы будем использовать, - это JSON, но не беспокойтесь, если вы не знакомы с ним... ни я =). Достаточно хорошо знать, что это способ форматировать текст, чтобы другие его части могли использовать его.

Данные, необходимые текстовому полю для автозаполнения, указаны в параметре источник:. Поскольку мы хотим отправить список имен людей и их идентификатор в автозаполнение, мы поставим в качестве источника следующее:

source: '<%= people_path(:json) %>'  

Помощник rails выше переведет строку "/people.json". Вам не нужно создавать страницу со словами "/people.json". То, что вам нужно сделать, это сообщить своему менеджеру людей, что делать, когда он получает запрос для/людей с форматом .json. Поместите в свой менеджер people_controller следующее:

def index  
# I will explain this part in a moment.
  if params[:term]
    @people = Person.find(:all,:conditions => ['given_name LIKE ?', "#{params[:term]}%"])
  else
    @people = Person.all
  end

  respond_to do |format|  
    format.html # index.html.erb  
# Here is where you can specify how to handle the request for "/people.json"
    format.json { render :json => @people.to_json }
    end
end

Теперь у всех людей в @people отправляется текстовое поле автозаполнения. Это приводит к следующему вопросу.


ФИЛЬТРНЫЕ ДАННЫЕ, ИСПОЛЬЗУЕМЫЕ ДЛЯ ПРЕДЛОЖЕНИЯ АВТОКОМПЛЕТЫ, ОСНОВАННЫЕ НА ВХОДЕ

Как текстовое поле автозаполнения знает, как фильтровать результаты в зависимости от того, что вы набираете?

Виджет автозаполнения, назначенный текстовому полю, отправит все, что вы введете, в текстовое поле в качестве параметра к вашему источнику:. Отправляемый параметр " term". Поэтому, если вы должны ввести "Joe" в текстовое поле, мы будем делать следующее:

/people.json?term=joe

Вот почему в контроллере есть следующее:

# If the autocomplete is used, it will send a parameter 'term', so we catch that here
    if params[:term]
# Then we limit the number of records assigned to @people, by using the term value as a filter.
      @people = Person.find(:all,:conditions => ['given_name LIKE ?', "#{params[:term]}%"])
# In my example, I still need to access all records when I first render the page, so for normal use I assign all. This has nothing to do with the autocomplete, just showing you how I used it in my situation.
    else
      @people = Person.all
    end

Теперь, когда мы ограничили количество записей, назначенных @people, в зависимости от того, что введено в текстовое поле автозаполнения, теперь мы можем превратить это в формат JSON для предложений автозаполнения.

respond_to do |format|  
      format.html # index.html.erb  
      format.json { render :json => @people.to_json }
    end 

Теперь просто просмотрите комментарии внутри "Большого фрагмента кода", который должен объяснить остальную часть того, как это связано.

В конце вы должны иметь текстовое поле на своей странице, которое будет действовать как автозаполнение и скрытое поле, которое отправит идентификатор в параметре вашего контроллера.


НАСТРОЙКА СОБСТВЕННОЙ АВТОКОМПЛЕКТЫ

Как только вы поймете вышеизложенное и хотите его изменить для своего использования, вы должны знать, что формат JSON, возвращаемый с вашего контроллера, выглядит следующим образом:

[{"person":{"id":1,"given_name":"joe","middle_name":"smith","family_name":"jones","nationality":"australian"}}]

Способ доступа к различным значениям из строки JSON в вашем javascript в этом случае будет:

ui.item.person.name_of_some_attribute_such_as_given_name

Довольно, просто. Очень похоже на доступ к атрибуту ActiveRecord в Rails.

Одна последняя заметка. Я потратил много времени на поиск другого способа предоставления скрытого значения, поскольку я думал, что эта функция должна быть встроена в виджет jquery. Однако, это не так. В официальном примере jQuery четко показано, что способ отправки другого значения, выбранного в качестве параметра, заключается в использовании скрытого поля.

Я надеюсь, что это поможет кому-то.

Дейл

Ответ 2

jQuery 1.9/1.10 удалил автозаполнение ключа и добавил uiAutocomplete

.data("uiAutocomplete") instead of .data("autocomplete")

После изменения выше, это сработало для меня.

Ответ 3

Dale Answer - довольно учебник. Следует отметить, что, используя свой первый запрос, источник данных будет возвращать совпадения начало с введенной вами строкой. Если вы хотите искать в любом месте слова, вам нужно изменить:

@people = Person.find(:all,:conditions =>
    ['given_name LIKE ?', "#{params[:term]}%"])

к

@people = Person.find(:all,:conditions =>
    ['given_name LIKE ?', "%#{params[:term]}%"])

(добавлен дополнительный % к запросу)

Ответ 4

В основном я следил за советом Dale ниже, но мои файлы с контроллером и js были немного различны, и версия по каким-то причинам давала мне проблемы (возможно, bc из jquery-обновлений)

Контекст: я пытаюсь автозаполнять имена диджеев, набранных пользователями - также newb

DJs Controller

 class DjsController < ApplicationController
    def index
     if params[:term]
       @djs = Dj.is_dj.where('lower(name) LIKE ?', "%#{params[:term].downcase}%")
       respond_to do |format|  
          format.html
          format.json { render :json => @djs.map(&:name) }
       end
     end    
   end
 end

html.erb файл

  <script type="text/javascript">

$(function() {  
    $('#select_origin').autocomplete({
        source: '<%= djs_path(:json) %>'
      })

    $('.submit-comment').click(function(){
      var dj_name = $('#select_origin').val();
      $('#link_origin_id').val(dj_name);
    })

})

</script>

Ответ 5

Это большая помощь.

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

def avatar_url
    avatar.url(:thumb)
end

И затем в контроллере вместо to_json используйте as_json

respond_to do |format|
    format.json {render :json => @users.as_json(:only => [:id,:name,:username], :methods => [:avatar_url]) }
end 

Ответ 6

Важно отметить, что если ваш "источник" относительно невелик, например, 50 элементов, реализация должна быть другой (и намного проще). Он упоминается в четвертом абзаце официального документа:

https://api.jqueryui.com/autocomplete/

При использовании локальных данных все, что вам нужно сделать, это получить данные и передать их методу автозаполнения, и он сделает фильтрацию для вас. Вам не нужно возвращаться на сервер каждый раз, когда вводится термин es.

function filterByTags(tags) {
  $("#stories-filter").autocomplete({
     source: tags,
     autoFocus: true
  });
}

$("#stories-filter").click(function() {
  $.ajax({
    dataType: 'json',
    method: 'GET',
    url: 'tags/index',
    data: $(this).data('project-id'),
    success: function (response) {
      if(response.success) {
        var tags = response.data.tags;
        filterByTags(tags);
      }
    },
    error: function (response) {
      if(response.status === 422) {
        var $errors = 'There are no tags in this project',
            $errorsContainer = $('.error-container');
        $errorsContainer.append($errors);
        $errorsContainer.show();
      }
    }
  });
});

Ответ 7

Поскольку это старое, но Google все еще приходит сюда, небольшая заметка о главном ответе, который по сути хорош, но некоторые вещи изменились:

  • см. ответ о том, что jquery изменил .data("uiAutocomplete") на .data("autocomplete")

  • Также я бы порекомендовал отдельный маршрут для коллекции ресурсов, которая просто обрабатывает json

  • используйте rabl для создания меньшего json (или вытащите для больших моделей)
  • Или, не как, для нечувствительных к регистру
  • % впереди, поэтому поиск не просто start_with.
  • Допустимый обход в методах, таких как item.person.name, это просто item.name (поэтому отбросьте .person)
  • употреблять кофе (в хамле)
  • используйте лимит и где, как в: Person.where('данное_имя ilike?', "% # {params [: term]}%"). limit (20)