我需要一些有关如何实施的帮助 jQuery-UI自动完成 在我的Rails应用程序中。

我想将自动完成添加到文本字段中,用户可以在其中输入客户名称。由于可以有数百个客户,因此我需要像从桌子上一样“远程”提取建议的自动完成值(至少这是我了解的)。

我未能理解的要点是如何为自动完成文本框提供建议的值。我已经阅读了jQuery-UI文档,但我似乎对此有些密集。

因此,我真正追求的是一个示例,说明了我如何在Rails应用程序中工作,而不一定是对JavaScript的构建方式的完整描述(这就是JQuery-UI团队为我所做的=))。

例如,如何准备自动完成的数据,以及如何将自动完成功能附加到文本框上。

有帮助吗?

解决方案

好吧,我从来没有回答过上面的问题,所以我最终不得不自己弄清楚。我认为我应该发布解决方案,以防万一还有其他人想知道同样的事情。

您应该知道的第一件事是,这是我对JavaScript的第一次体验,而我只是掌握了Rails。因此,一定要随时进行编辑,在任何您觉得我对此出错的任何地方发表评论。对与错,至少我知道它可以按照我想要的方式发挥作用。

我认为以身作则的最好方法是。因此,以下是我如何将自动完成的小部件在应用程序中工作。即使您不了解发生了什么,您也可以继续将以下代码放入应用程序中,然后我们可以仔细研究每个部分的工作方式。之后,您应该掌握如何修改它以供使用或折射。


在您的Rails应用程序中包括JQuery UI。

下载副本 jQuery UI 和位置 jquery-ui-1.8.2.custom.min.js 你内心 /public/javaScript 目录。另外,请确保您拥有jQuery本身的副本,并且它也在同一文件夹中。

将jQuery UI文件和jQuery文件包括在您的 application.html.erb 这样的文件。
(只要匹配,您就可以随意命名文件)

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

在下载JQuery UI中,您将拥有一个包含所有CSS数据的文件夹。这个名称会根据您选择的主题而有所不同,例如我选择了主题'库比蒂诺'。将包含您CSS数据的整个文件夹放入'/public/stylesheets/'。然后在您的应用程序中包含CSS文件。html.erb。

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


示例自动完成JavaScript

现在,取以下代码并将其放在您的其中一个新的'视图。您可以在任何视图中使用它,但要意识到我已经从属于“ links_controller”的控制器的现有视图中获取了它,并且它正在从“ People_Controller”中删除数据。希望您对铁轨有足够的了解,可以解决您需要更改的内容,因此这对您有用。

- 开始大量代码 -

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

- 结束大量代码 -

现在可以连接点。


提供用于自动完成的数据,以作为建议

首先,将自动完成的TextField可以在下拉列表中显示的一些数据连接。我们将使用的格式是JSON,但是如果您不熟悉它,请不要担心... i =)。足够好,可以知道这是一种格式化文本的方法,以便您/其他应用程序的其他部分可以使用它。

在'来源:' 选项。因为我们想将人们名称及其ID的列表发送到自动完成,所以我们将以下内容作为来源。

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

上面的导轨辅助人员将转化为绳子”/people.json“。您不需要创建一个页面”/people.json“。您需要做的是告诉您的People_Controller在收到.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中的所有人发送到自动完整的Textfield。这提出了下一个点。


根据输入,用于自动完成建议的过滤数据

自动完成的TextField如何根据您的键入键入结果?

分配给TextField的自动完成的小部件将把您输入的任何内容作为参数发送到您的源:发送的参数为“学期“因此,如果您要在Textfield中输入“ 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

现在,我们已经根据键入的TextField键入的内容限制了分配给@People的记录数量,我们现在可以将其转换为JSON格式的自动完整建议。

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

现在,只需查看“代码大块”中的评论,这些评论应该解释其余的联系方式。

最后,您的页面上应该有一个文本字段,该文本字段充当自动完成和隐藏字段,该字段将在参数中将ID发送到您的控制器。


自定义您自己的自动完成

一旦了解了上述内容,并且要修改它以供使用,您应该知道从控制器返回的格式JSON看起来像这样:

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

在这种情况下,从JavaScript中的JSON字符串访问不同值的方法将是:

ui.item.person.name_of_some_attribute_such_as_given_name

漂亮,简单。很像在铁轨中访问ActiverEcord属性。

最后一个音符。我花了很多时间寻找另一种提供隐藏价值的方式,因为我认为该功能应该是嵌入式窗口小部件中的。然而,这种情况并非如此。在官方jQuery示例中清楚地显示了发送另一个值然后选择参数的方式的方法是使用隐藏的字段。

好吧,我希望这对某人有帮助。

戴尔

其他提示

jQuery 1.9/1.10删除了密钥自动完成并添加了uiautocomplete

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

修改上面后,它对我有用。

戴尔的答案 是一个教程。要注意的一件事是,使用您的第一个查询,数据源只会返回匹配项 开始 使用您键入的字符串。如果您想在单词中的任何地方进行搜索,则需要更改:

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

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

(额外添加 % 查询)

我基本上遵循了Dale的建议,但我的控制器和JS文件有些不同 - 他的版本出于某种原因给了我问题(也许是JQuery更新的BC)

上下文:我正在尝试自动完成用户键入的DJ的名称 - 也是一个newb

DJS控制器

 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>

这是一个很好的帮助。

除此之外,如果您需要获取用户图像的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 

重要的是要注意,如果您的“源”相对较小,例如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();
      }
    }
  });
});
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top