52

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

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

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

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

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

ответ

145

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

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

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


ВКЛЮЧИТЬ JQUERY UI IN YOUR RAILS APP.

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

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

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

В загружаемое JQuery UI, вы будете иметь папку, содержащую все данные 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, чтобы понять, что вам нужно изменить, чтобы это сработало для вас.

- Begin большой кусок кода -

<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 %> 

- Конец Большой кусок кода -

Хорошо, теперь соединить точки.


ПРЕДОСТАВЛЕНИЯ ДАННЫХ ДЛЯ автозаполнения ИСПОЛЬЗОВАТЬ КАК ПРЕДЛОЖЕНИЙ

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

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

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

Хелпер рельсы выше переведут в строку "/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 отправляется на автозаполнения текстовое поле. Это поднимает следующий вопрос.


ФИЛЬТР данные, используемый для Autocomplete внушения, на основе входных данных

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

Виджет автозаполнения, назначенный текстовому полю, отправит все, что вы введете, в текстовое поле в качестве параметра к вашему источнику :. Отправляемый параметр: «термин».Так что если вы должны были ввести «Джо» в текстовое поле, мы будем делать следующее:

/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 

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

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


CUSTOMIZE СВОЙ Autocomplete

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

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

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

ui.i tem.person.name_of_some_attribute_such_as_given_name

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

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

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

Dale

+2

Спасибо. Это была большая помощь. – rangalo

+2

Хорошее объяснение. Вокруг места много разных советов и трюков, но до сих пор я не нашел одного краткого, сквозного примера. Спасибо за помощь ... – Nuby

+3

@paz у вас должен быть собственный блог, если вы этого еще не сделали :) очень приятно, только то, что я искал. – jn29098

2

Это отличная помощь.

В дополнение к этому, если вам нужно получить 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 
7

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

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

в

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

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

10

JQuery 1,9/1,10 удалили ключ автозаполнения и добавил uiАвтокомплект

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

После внесения изменений в abov e, это сработало для меня.

+0

Это должен быть лучший ответ. –

4

В основном я последовал совет Дейл ниже, но мой контроллер и JS файлы были немного diff- его версия дает мне вопросы, по какой-то причине (возможно, Ьс из Jquery обновлений)

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

диджеев контроллер

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> 
1

Важно отметить, что если ваш «источник» относительно невелик, например 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(); 
     } 
    } 
    }); 
}); 
Смежные вопросы