Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 5 Live Search with Keyup losing input focus Turbolinks

I have a rails 5.1.3 app that's a basic contact model (handy names and numbers). I'm using ransack to search on the index view/page. I'm using coffeescript to listen to a keyup event on the input and it's working, firing as I type (per the rails dev logs) but the the input on the form loses focus and the partial doesn't continue to refresh as I click back into the put and type. I'm thinking this is a Turbolinks issue, but I'm not sure.

Here is my controller: contacts_controller.rb excerpt

class ContactsController < ApplicationController

  def index
    @q = Contact.ransack(params[:q])
    @contacts = @q.result(distinct: true).order("name asc").paginate(:page => params[:page], :per_page => 2)
    respond_to do |format|
      format.html
      format.js  {render "index", :locals => {:contacts => @contacts}}
    end
  end
end

Here is my index view index.html.erb

 <%= link_to "New Contact", '#contact-modal', data: {toggle: "modal", target: "#contact-modal" }, class: 'btn btn-info btn-sm'  %>
<%= render 'shared/contact_modal' %>
<div id="search">
  <%= render 'contacts/search' %>
</div>

<div id="results">
  <%= render 'contacts/results', contacts: @contacts %>
</div>

Here is my js file index.js.erb

$("#search").html("<%=j render :partial => 'contacts/search' %>")
$("#results").html("<%=j render :partial => 'contacts/results', locals: {contacts: @contacts} %>")

Here are the partials for search and results

 <%= search_form_for(@q, url: "/contacts", method: :get, id: "contacts_search", remote: true) do |f| %>
  <%= f.search_field :name_or_address_or_office_number_or_home_number_or_mobile_number_or_fax_number_or_email_or_misc_info_cont, placeholder: 'Search...', class: 'form-control' %>
  <%= f.submit %>
<% end %>



 <table class="table table-striped">
  <thead class="thead-default">
    <tr>
      <th>Name</th>
      <th>Company Name</th>
      <th>Office Number</th>
      <th>Mobile Number</th>
      <th>Home Number</th>
      <th>Address</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
    <% contacts.each do |contact| %>
    <tr>
      <td><%= link_to "#{contact.name}", contact_path(contact) %></td>
      <td><%= contact.company_name %>
      <td><%= contact.office_number %></td>
      <td><%= contact.mobile_number %></td>
      <td><%= contact.home_number %></td>
      <td><%= contact.address %></td>
      <td><%= contact.email %></td>
    </tr>
    <% end %>
  </tbody>
</table>
<%= will_paginate contacts, renderer: WillPaginate::ActionView::BootstrapLinkRenderer %>

Here is my contacts.coffee file

$(document).on 'turbolinks:load', ->
  $('#contacts_search input').keyup ->
    $.get $('#contacts_search').attr('action'), $('#contacts_search').serialize(), null, 'script'
    false

Here is an excerpt of the development.log which shows the method being fired, but my partial is not refreshing. It fires one letter and stalls completely, losing focus on the form input.

Am I missing something here or is my coffeescript wrong?

 Started GET "/contacts?utf8=%E2%9C%93&q%5Bname_or_address_or_office_number_or_home_number_or_mobile_number_or_fax_number_or_email_or_misc_info_cont%5D=a&_=1504386143674" for 127.0.0.1 at 2017-09-02 16:02:25 -0500
Processing by ContactsController#index as JS
  Parameters: {"utf8"=>"✓", "q"=>{"name_or_address_or_office_number_or_home_number_or_mobile_number_or_fax_number_or_email_or_misc_info_cont"=>"a"}, "_"=>"1504386143674"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 7], ["LIMIT", 1]]
  Role Load (0.1ms)  SELECT  "roles".* FROM "roles" WHERE "roles"."name" = $1 LIMIT $2  [["name", "disabled"], ["LIMIT", 1]]
  Role Load (0.1ms)  SELECT  "roles".* FROM "roles" WHERE "roles"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  CACHE Role Load (0.0ms)  SELECT  "roles".* FROM "roles" WHERE "roles"."name" = $1 LIMIT $2  [["name", "disabled"], ["LIMIT", 1]]
  Rendering contacts/index.js.erb
  Rendered contacts/_search.html.erb (1.4ms)
  Contact Load (0.7ms)  SELECT  DISTINCT "contacts".* FROM "contacts" WHERE ((((((("contacts"."name" ILIKE '%a%' OR "contacts"."address" ILIKE '%a%') OR "contacts"."office_number" ILIKE '%a%') OR "contacts"."home_number" ILIKE '%a%') OR "contacts"."mobile_number" ILIKE '%a%') OR "contacts"."fax_number" ILIKE '%a%') OR "contacts"."email" ILIKE '%a%') OR "contacts"."misc_info" ILIKE '%a%') ORDER BY name asc LIMIT $1 OFFSET $2  [["LIMIT", 2], ["OFFSET", 0]]
   (0.3ms)  SELECT COUNT(DISTINCT "contacts"."id") FROM "contacts" WHERE ((((((("contacts"."name" ILIKE '%a%' OR "contacts"."address" ILIKE '%a%') OR "contacts"."office_number" ILIKE '%a%') OR "contacts"."home_number" ILIKE '%a%') OR "contacts"."mobile_number" ILIKE '%a%') OR "contacts"."fax_number" ILIKE '%a%') OR "contacts"."email" ILIKE '%a%') OR "contacts"."misc_info" ILIKE '%a%')
  Rendered contacts/_results.html.erb (3.7ms)
  Rendered contacts/index.js.erb (9.6ms)
Completed 200 OK in 32ms (Views: 25.8ms | ActiveRecord: 1.6ms)
like image 311
nulltek Avatar asked Aug 27 '17 17:08

nulltek


1 Answers

What was actually happening was that the JS would fire and my search form partial would get reloaded. So I changed this:

$("#search").html("<%=j render :partial => 'contacts/search' %>")
$("#results").html("<%=j render :partial => 'contacts/results', locals: {contacts: @contacts} %>")

To This:

$("#results").html("<%=j render :partial => 'contacts/results', locals: {contacts: @contacts} %>")

And it works perfectly.

like image 108
nulltek Avatar answered Oct 16 '22 19:10

nulltek