I've integrated Ransack into my Rails app, I use it via ajax post, soso in t he index.html.erb it uses the _partner.html.erb
But when I get back empty search result, I would like to achieve display a "No result" text.
I've tried it this way(in index.js.erb):
$('#partners_list').html('<% if #partners %> <%= escape_javascript render(#partners) %> <% else %><li class="collection-item">No result</li><% end %>');
$('nav.pagination').html('<%= escape_javascript(paginate(#partners, :remote => true).to_s) %>');
But this is not work, cause if there aren't any search result it will generate this javascript code:
$('nav.pagination').html(' ');
$('nav.pagination').html('');
This will not insert any <li> elements into the <ul>
(index.html.erb)
<ul id="partners_list" class="collection margin-0-minus-15 z-depth-2">
<%= render #partners %>
</ul>
(I've tried handle here in the index.html.erb too, but it seems if there is no search result then the #partners does not exist... because the <%= debug(#partners) %> will not show nothing on the view if the search result is empty)
This is my action:
def index
#search = Partner.where(is_active: true).search(params[:q])
#partners = #search.result.includes(:user, :county).order(created_at: :desc).page(params[:page])
end
How can I achieve when I the back-end searching response with empty result, then the application display an "Empty result" text?
Have u tried with if else statement outside the html('')?
<% if #partners.any? %>
$('#partners_list').html("<%= j render(#partners) %>")
<% else %>
$('#partners_list').html("<li class="collection-item">No result</li>")
<% end %>
Related
I've got an index page with a search which mostly works, aside from when there are no results, which is when I get the error:-
response has no matching <turbo-frame id="events"> element
I don't get this when there are search results. Do I need to specify a partial to render in my index action, when results are empty? Why isn't this being evaluated in my view?
index.html.erb
<div id="events-wrapper">
<% if #events.any? %>
<%= render "events", events: #events %>
<% else %>
<%= render "no_events" %>
<% end %>
</div>
_events.html.erb
<%= turbo_frame_tag "events" do %>
<%= render collection: #events, partial: 'event' %>
<%= raw pagy_bootstrap_nav(#pagy) %>
<% end %>
_no_events.html.erb
<div class="no-events-notice alert alert-primary">
No events found
</div>
events_controller.rb index action
def index
#pagy, #events = pagy(find_events(filter_params))
end
Basically my search works fine, but when there are no results - my no_events partial doesn't get rendered, unless I refresh the page. What am I missing?
I've removed the partial from the equation and just replaced that line with a simple div instead and it's still not displayed.
The solution was to wrap the results in a turbo frame with an id of "events" like so:-
<turbo-frame id="events">
<% if #events.any? %>
<%= render "events", events: #events %>
<% else %>
<%= render "no_events" %>
<% end %>
</turbo-frame>
I am building webstore. I added a bit of AJAX functionality to add, update and remove items from my cart without refreshing.
It works perfect as long as there are no items in a cart and render cart_empty partial properly.
The problem is when I add few items, and I can update/remove them without refreshing and
finally I remove the last one, and it do not switch to the cart_empty partial and there are only empty table headers left from cart-items partial.
Can I add some logic to destroy.js.erb?
destroy.js.erb
$("#cart-item").html("<%= j render 'carts/cart_items' %>");
the show.html.erb contains this unless function:
<% unless current_order.order_items.empty? %>
<div id="cart-item">
<%= render 'cart_items' %>
</div>
<% else %>
<div id="cart-empty">
<%= render 'cart_empty' %>
</div>
<% end %>
Maybe should I modify somehow my controller to check if there are order_items in a current_order?
Thank you!
A JS.erb template is evaluated in exactly the same way as a HTML template. So you can just add a condition:
<% if current_order.order_items.any? %>
$("#cart-item").html("<%= j render 'carts/cart_items' %>");
<% else %>
$("#cart-item").html("<%= j render 'carts/cart_empty' %>");
<% end %>
None that this implies that current_order is either a helper or a local passes to the view.
But you might want to refactor this and push the condition down to the partial:
# carts/cart_items.html.erb
<% if cart_items.none? %>
<% render :cart_empty %>
<% else %>
# ...
<% end %>
Which will let you just write:
<%= render 'carts/cart_items', cart_items: current_order.order_items %>
See:
Layouts and Rendering in Rails - passing local variables
New to AJAX and search. I feel like I'm an inch away on this one, but I'm not sure what to fix. Also, my controller looks really hacky to me right now.
At any rate, I'm trying to create a search that allows users to search through blog posts on my page using AJAX. Here are the (relevant parts of the) parts:
posts_controller.rb
def show
#posts = Post.all.reverse
#post = Post.find(params[:id])
#link_num = 10
respond_to do |format|
format.html # show.html.erb
format.json { redirect_to #post }
end
end
def search
#link_num = 10
#posts = Post.all.reverse
#post = Post.find(params[:id])
#The including function returns the search results
#search = Post.first.including(params[:term])
render 'show'
end
What strikes me as "hacky" here is that I repeat all the variable assignments (there are others I didn't show cause they're not relevant). Shouldn't an AJAX call ideally not have to redefine/reload all these variables? Also, I have to pass :id to my search action through a hidden field. This feels weird/wrong to me.
show.html.erb
<h1 class="squeeze">Recent Posts</h1>
<%= form_tag("/search", method: "get", class: "search") do %>
<%= text_field_tag(:term, '', placeholder: "Search posts:") %>
<%= hidden_field_tag(:id, #post.id) %>
<%= submit_tag("Search", class: "btn search_button", remote: true) %>
<% end %>
<% if !#search%>
<ul>
<% #posts.first(#link_num).each do |p| %>
<li>(<%= p.created_at.strftime("%b %d, %Y") %>)</span></li>
<% end %>
<% if #posts.length > #link_num %>
<div class="link_disclaimer">
<h4>---</h4>
<h5><%= "Only showing #{#link_num} most recent posts." %></h5>
<h5>Search to narrow results.</h5>
</div>
<% end %>
</ul>
<% elsif #search.empty? %>
<h3>Term not found!</h3>
<% else %>
<ul>
<% #search.first(#link_num).each do |p| %>
<li>(<%= p.created_at.strftime("%b %d, %Y") %>)</span></li>
<% end %>
<% if #search.length > #link_num %>
<div class="link_disclaimer">
<h4>---</h4>
<h5><%= "Only showing first #{#link_num} relevant hits." %></h5>
<h5>Narrow search for more specific results.</h5>
</div>
<% end %>
</ul>
<% end %>
routes.rb
match '/search', to: 'posts#search'
Currently, the search itself works fine, with three major problems:
The aforementioned messiness of my Controller.
The fact that the whole page reloads. Isn't that the opposite of what AJAX is supposed to do? How can I get it to reload just the list of links?
The URL. It's super messy (i.e "/search?utf8=✓&term=limits&id=11&commit=Search"). I'd ideally have it remain untouched by the search, but if that's not possible, maybe just something like "/search?=". How's that done?
Based on the comment here is basic logic to make the function work(Sorry for no real code as that is too time consuming)
In controller you make a method say "search". The method need an argument which is the phrase to search. It gets the result from db and respond to JSON only with the result.
In template you have a search form.
In JS, you listen the event of user clicking the submit button, catch the characters they write, and handle it to ajax function.
Write Ajax code, preferred using jQuery's ajax(). Basically use ajax() to send the typed characters to controller method in #1 as argument. Then ajax() will get the response(the search result) from server.
Update the result in DOM. You can either add a new div to show search result, or replace current main content div to show result.
The case is when user click an add link, if the url already added, there will be a alert otherwise will display a form to add new bookmark. The code below works quite well for checking the duplicated url, but if the url is not duplicated I just don't know how to render a add bookmark (in this case the page will be loaded like a normal non ajax request)
This is the link in view
<%= link_to "add", user_bookmark_add_path(current_user, bookmark), remote: true %>
The link will invoke the controller action add
# controllers/bookmarks_controller.rb
def add
#bookmark = Bookmark.find(params[:bookmark_id])
respond_to do |format|
format.js
end
end
The javascript file
# views/bookmarks/add.js.erb
<% if duplicated_url? #bookmark.url %>
alert("Duplicated")
<% else %>
# how to render the new bookmark form here
<% end %>
Any suggestion ? Thanks
Create a partial for new bookmark form.
_form.html.erb
<%= form_for(bookmark) do |f| %>
<%= f.text_field :name %>
<%= f.submit "submit" %>
<% end %>
Add id to your link
.html.erb
<%= link_to "add", user_bookmark_add_path(current_user, bookmark), remote: true, id: "bookmark" %>
Replace your link with partial.
.js.erb
<% if duplicated_url? #bookmark.url %>
alert("Duplicated")
<% else %>
$("#bookmark").replaceWith("<%= j render "form", bookmark: Bookmark.new %>");
<% end %>
On your add.js.erb file, in the else part of the code you can append a partial to your list like this:
$('#your_list').append(
"<%= escape_javascript(render('your_item_of_the_table_partial')) %>"
);
This partial can be a list item, a table row, a div with your content, anything. The thing is, you will need a chunk of html to be re-rendered on your screen with the new content.
Example of a list item partial:
# _bookmark_item.html.erb
<li><%= #bookmark.url %> </li>
Try something like this:
$('#your_div_id').append('<%= escape_javascript(raw render :partial => 'your_form_partial') %>')
This will add the contents of your ruby partial to the DOM.
I am using metasearch. I want to search for friends using email.
In my users controller:
def index
#search = User.search(params[:search])
#users = #search.all
end
In my view:
<%= form_for #search do |f| %>
<div class="prepend-top field">
<%= f.label("Primary email address") %></br>
<%= f.text_field(:email_matches) %>
</div>
<div class="prepend-top field">
<%= f.label("School email address") %></br>
<%= f.text_field(:school_email_matches) %>
</div>
<div>
<ul>
<% if params[:search].blank? %>
Your search results here.
<% else %>
<% #users.each do |user| %>
<li class="box round">
<%= user.name %></br>
</li>
<% end %>
<% end %>
</ul>
</div>
The way it is now, the results are displayed on an adjacent column on the same page. I am trying to have it so that if the search form is blank then it returns a blank search.
Problems:
When I go to the page initially, the search results side is blank and does say "Your search results here". But, when I just click on the search button without putting anything in the search fields, it returns a list of all the users on the search result column. How do I make it so that a blank search form truly returns a blank page?
How do I go about making it so that it shows "No results for your search criteria"? if there are no matches for the particular search?
Thanks.
Part of your problem is happening because when you search for an empty string, your search function returns all your users.
So, in your controller, you could do:
def index
if params[:search]
empty_search = params[:search].keep_if {|k, val| !val.blank?}.empty?
else
empty_search = true
end
if empty_search
# no search was submitted, or search params are all blank
#search = ""
#users = []
else
# a search was submitted
#search = User.search(params[:search])
#users = #search.all
end
end
(not sure about the exact terminology for the condition, but basically, if you're passing an empty string or nothing, you should run the 'else' piece of the code).
In the view, you could do:
<% if #search.blank? %>
Your search results here.
<% else %>
<% if #users.blank? %>
No results for you
<% else %>
<ul>
<% #users.each do |user| %>
<li class="box round">
<%= user.name %></br>
</li>
<% end %>
</ul>
<% end %>
</ul>
Would that work?