1

I have implement jQuery-ui autocomplete in my Rails app and it works fine, but i want also the results to be links to the products (e.g. products/1). Any idea how can i do it?

jQuery code in coffeescript:

$(document).on "page:change", ->
  $(".header-search-input").autocomplete(
    minLength: 2,
    source: $(".header-search-input").data('autocomplete-source')
    select: (event, ui) ->
      $(".header-search-input").val ui.item.label
  ).autocomplete('instance')._renderItem = (ul, item) ->
    result = item.label.replace(new RegExp('(?![^&;]+;)(?!<[^<>]*)(' + $.ui.autocomplete.escapeRegex(@term) + ')(?![^<>]*>)(?![^&;]+;)', 'gi'), '<strong>$1</strong>')
    $('<li>').append('<a>' + result + '</a>').appendTo ul

  return

View:

<ul class="nav navbar-nav navbar-left" id="header-search">
  <%= form_tag search_path, class: "navbar-form navbar-left list-inline", method: :get do |f| %>
    <li class="form-group">
      <%= text_field_tag :q, params[:q], class: "form-control margdown header-search-input", placeholder: "Search", data: { autocomplete_source: products_path(:json) } %>
    </li>
    <li><%= submit_tag "Submit", class: "btn btn-info shake", name: nil %></li>
  <% end %>
</ul>

Controller:

  def index
    if params[:term]
      @products = Product.order(:name).where(Product.arel_table[:name].matches("%#{params[:term]}%"))
      response = (Hash[@products.map { |u| [u.name, u.id] }])
    else
      @products = Product.all.where.not(quantity: 0).order(created_at: :desc).paginate(page: params[:page], per_page: 9)
    end

    respond_to do |format|
      format.html
      format.json { render json: response.keys }
    end
  end

I have create a hash as you can see at the controller, with pairs of names and ids, to get the id of the corresponding product name in the view. (You can ignore it is just a thought.) The problem is that i don't know how to do this.

Gregory_ynwa
  • 168
  • 1
  • 3
  • 16

1 Answers1

0

Finally i find a solution. I post it in case someone in future need something like this.

First in 'config/initializers/wrap_parameters.rb', i uncomment the following:

ActiveSupport.on_load(:active_record) do
 self.include_root_in_json = true
end

You can read more about this here and here. Now the json response from controller will be in format like this:

"[{\"product\":{\"id\":20,\"name\":\"Andrew Beer\"}},{\"product\...]"

controller:

  def index
    if params[:term]
      @products = Product.order(:name).where(Product.arel_table[:name].matches("%#{params[:term]}%"))
    else
      @products = Product.all.where.not(quantity: 0).order(created_at: :desc).paginate(page: params[:page], per_page: 9)
    end
    respond_to do |format|
      format.html
      format.json { render json: @products, only: [:id, :name] }
    end
  end

and now we can access both parameters (id and name) in our js file.

jQuery:

$(document).on "page:change", ->
  $(".header-search-input").autocomplete(
    minLength: 2,
    source: $(".header-search-input").data('autocomplete-source')
    select: (event, ui) ->
      $(".header-search-input").val ui.item.product.name
      $("a").attr("href", "/products/"+ ui.item.product.id)
  ).autocomplete('instance')._renderItem = (ul, item) ->
    result = item.product.name.replace(new RegExp('(?![^&;]+;)(?!<[^<>]*)(' + $.ui.autocomplete.escapeRegex(@term) + ')(?![^<>]*>)(?![^&;]+;)', 'gi'), '<strong>$1</strong>')
    $('<li>').append('<a>' + result + '</a>').appendTo ul

  return
Community
  • 1
  • 1
Gregory_ynwa
  • 168
  • 1
  • 3
  • 16