Pedro Vieira
Pedro Vieira

Reputation: 2316

How to send a selected element and a text input via jQuery

My app has a live search implemented and it works properly. The problem that I have is that now I have a table with a lot of columns and I want to search through all elements. I want to have only one text input and a drop down that will select the column that I want to search in.

Searchable module

module Searchable
  extend ActiveSupport::Concern

  module ClassMethods
    def search_for(present_column,record)
      record.present? ? where(present_column+' LIKE ?', record+"%") : all
    end
  end
end

People controller

class PeopleController < ApplicationController
  def index
    @people = Person.page(params[:page]).per(5).search_for(params[:object_columns], params[:search])
  end

The search engine

<%= form_tag do %>
  <% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
  <%= select_tag :object_columns, options_for_select(valid_column_names) %>
  <%= text_field_tag :search, '', autocomplete: :off %>
<% end %>

The live search js

$(function () {
    $("input#search").keyup(function () {
        $.get($("#object_columns option:selected").text(), $("#object_columns").serialize(), null, "script");
        $.get($("#search").attr("action"), $("#search").serialize(), null, "script");
    });
});

The input text is returned as expected, but nothing comes from the object_columns. When I type the word "n", for example, my server terminal returns this message:

Started GET "/people?&search=n&_=1463081307356" for 127.0.0.1 at 2016-05-12 16:28:34 -0300
Processing by PeopleController#index as JS
  Parameters: {"search"=>"n", "_"=>"1463081307356"}

EDIT:

I had an idea later on and made some changes. I gave the form an ID and used it to do the request, now I can have both information (column names and the search record) at the same time. The only problem now is with the path, it is returning an URI error.

The search engine

<%= form_tag people_path, class: "form_id" do %>
  <% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
  <%= select_tag :object_columns, options_for_select(valid_column_names) %>
  <%= text_field_tag :search, '', autocomplete: :off %>
<% end %>

The live search

$(function () {
    $("input#search").keyup(function () {
        $.get($(".form_id"), $(".form_id").serialize(), null, "script");null, "script");
    });
});

Upvotes: 2

Views: 111

Answers (1)

Michael Gaskill
Michael Gaskill

Reputation: 8042

In your search_for method, the return value is always all. You really want the return value to be the result of the ternary operator directly above it. Remove the last all and you should be good to go.

module ClassMethods
  def search_for(present_column,record)
    record.present? ? where(present_column+' LIKE ?', record+"%") : all
    # all  <== this should be removed
  end
end

In your javascript, you'll need a few changes:

$(function () {
    function search() {
        $.get("/search", { column_name: $("select#column_name").val(), search: $("#search").val() }, null, "script");
    };

    $("select#column_name").change(search); 
    $("input#search").keyup(search);
});

The actual Ajax call has been changed to:

  • remove the undefined "action" attribute on the search input field
  • explicitly reference the URL to send the request
  • create hash parameters for the ajax call
  • remove the unnecessary calls to serialize()

This also installs a handler on the change event of the column selection, hence the refactoring of the Ajax call to a separate function.

Upvotes: 1

Related Questions