Reputation: 2316
I am implementing a live search with a drop down containing multiple fields to filter through.It starts with only one search field, a drop down to select what to be searched for and a button to add more filters, when the user click the button, it generate a new field like this:
This image sample was done hard coded with the html inside the JavaScript. The problem is that I will use it in a lot of views so I need it to be dynamic as the code I previously done with Ruby to generate the first search field. I tried doing this way, but no success was achieved.
live_search.js.erb
$(function () {
function search() {
$.get(window.location.href, { object_columns: $("select#object_columns").val(), search: $("#search").val() }, null, "script");
};
$("select#object_columns").change(search);
$("input#search").keyup(search);
$('button').on('click',function(){
column = "<%= j render 'shared/search_engine' %>";
$('#search-form').after(column);
});
});
search_engine.html.erb
<div id="search-form">
<%= 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 %>
<%= button_tag "+" %>
</div>
I even tried to call the "search-form" in the JavaScript to replicate the code when the button was clicked but I read that it is not possible.
EDIT
I made some changes as @ppascualv suggested, but I still can't render and add another "search_engine" when I click the button. I am getting an error saying undefined method 'render'.
live_search.js.erb
$(function () {
function search() {
$.get(window.location.href, { object_columns: $("select#object_columns").val(), search: $("#search").val() }, null, "script");
};
$("select#object_columns").change(search);
$("input#search").keyup(search);
$('button').on('click',function(){
$('button').append("<%= escape_javascript(render @search_engine) %>");
});
});
search_engine.html.erb
<div id="search-form">
<%= form_tag({controller: "house_activities", action: "index"}, method: "get", remote: true) do %>
<% valid_column_names = HouseActivity.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 %>
<%= button_tag "+" %>
</div>
house_activities_controller.rb
class HouseActivitiesController < ApplicationController
before_action :set_house_activity, only: [:show, :edit, :update, :destroy]
def index
@house_activities = HouseActivity.page(params[:page]).per(5).search_for(params[:object_columns], params[:search])
respond_to do |format|
format.js
format.html
end
end
end
Upvotes: 0
Views: 3251
Reputation: 2316
I was able to solve my problem. I discovered that you can't render things in assets and you can't use ruby inside a JavaScript file. I did some workaround and got it done, I included the JavaScript code inside the html.erb file using the <script> JavaScript code </script>
syntax as shown here:
<script type="text/javascript">
column =
'<%= form_tag({controller: "people", action: "index"}, method: "get", remote: true) do %>' +
'<% valid_column_names = Person.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>' +
'<%= j (select_tag :object_columns, options_for_select(valid_column_names)) %>' +
'<%= text_field_tag :search, '', autocomplete: :off %>' +
'<% end %>';
$('button').on('click',function(){
$('button').after(column);
});
</script>
Because the select_tag ruby line generated a sentence with lots of quotation marks, the j used is the same as escape_javascript and it is used to format a sentence so the JavaScript can read it properly.
Upvotes: 0
Reputation: 174
You could do something like:
search_engine.html.erb
<%= form_tag(target_path, method: :get) do %>
<%= text_field_tag :query, nil, placeholder: "Search by column names...", class: "form-control search-form" %>
<% end %>
live_search.js
$(document).on("change", ".search-form", function() {
return $(this).parents("form").submit();
});
Then in your target model, you could add a search
scope to make it dynamic.
target.rb
class Target < ActiveRecord::Base
scope :search, -> (query) {
return if query.blank?;
where("target.column_name1 ILIKE :query or target.column_name2 ILIKE :query or target.column_name3 ILIKE :query", query: "%#{query}%")
}
end
And in your targets_controller.rb
class TargetsController < ApplicationController
def search_engine
@targets = Target.search(params[:query])
end
end
Upvotes: 0
Reputation: 1137
You should take a look at Javascript with Rails, for achive your proposit you will need to create a controller that responds with your js.erb, and this action should be called from a link with data-remote=true
or from ajax.
Upvotes: 1