Remote: true not working after submit via Jquery - ruby-on-rails

Im submitting my form with checkboxes via Jquery with remote true but its not working. Its keeps rendering the html format in the controller and i can work out why.
Here is my submit button and form:
<%= button_to "Read sel", root_path, class: "btn btn-info btn-sm padlr", id: "notification-submit" %>
<%= form_tag read_selected_notifications_path, :authenticity_token => true, remote: true ,id: "notification-form" do %>
<% #notifications.each do |x| %>
<div class="notification-body flerowspb">
<div class="flerowspb" style="width:80%">
<div class="notif-check flecolcen">
<%= check_box_tag "read_notif[]", value="#{x.id}" %>
</div>
<div class="notif-details ">
<div class="notif-time flerowspb">
<% if !x.viewed %>
<span class="glow"> New <%= x.notification_type.capitalize %></span>
<% else %>
<span><span class="text-grey"> New <%= x.notification_type.capitalize %></span></span>
<% end %>
<span class="text-grey font-small"> <%= time_ago_in_words(x.created_at) %> ago</span>
</div>
<div class="notif-body font-medium text-grey">
<span class="text-blue"><%= link_to x.sender.username, profile_path(x.sender) %> </span> <%= x.title %> <br>
Click <span class="text-blue"><%= link_to "Here", entry_path(x.entry_id, notification_id: x.id) %> </span> to view it
</div>
</div>
</div>
<div class="notif-image">
<%= image_tag x.entry.image.small_thumb %>
</div>
</div>
<% end %>
<% end %>
So there is no actual submit button for the form as i want the button above the form not below it like this,
I understand i have to add :authenticity_token => true as rails doesnt add this to form_tag with remote: true
Here is my controller:
def read_selected
Notification.read_selected(current_user.id, params[:read_notif])
respond_to do |format|
format.html{
flash[:success] = "Selected notifications marked as read"
redirect_to notifications_path
}
format.js{
render 'notifications/jserb/read_selected'
}
end
end
Here is the js code:
$(document).on('turbolinks:load', function(){
if (window.location.href.match(/\/notifications/)) {
$('#notification-submit').on('click', function(e){
console.log('oisdjfilds');
e.preventDefault();
$('#notification-form').submit();
});
}
});
EDIT: I added in a submit button at the bottom of the form and it works as it should do, So it something to do with the way i'm submitting the form

I assume you're using Rails 5, since there is such an inconsistency in its behavior. Please, check out the issue
As far as I understand the quick solution for your problem is going to be:
Get the form HTML element:
form = document.getElementById('notification-form');
or
form = $('#notification-form')[0]
And then fire Rails submit:
Rails.fire(form, 'submit');
or
form.dispatchEvent(new Event('submit', {bubbles: true}));

Related

Use of check_box_tag, how get his value?

I´m working to generate a PDF file with an option, this option makes visible a logo in the final PDF, I´m new in this and can´t hit the right answer
I made a plain check_box and then tried to catch a parameter, but this don´t work: <%= check_box_tag :logoless, "true", true %>
<a href="<%= pcf_generator_path(#legal_vacation, logoless: :logoless )%>" data-toggle="tooltip" data-placement="bottom"
title="Comprobante de Feriado"class="btn btn-primary" role="button" aria-pressed="true" target= '_blank'>
<%= "PCF" %></a>```
I want to be able to catch the value of a checkbox in url or in #legal_vacation variable (or directly if it´s possible).
http://localhost:3000/legal_vacations/pcf_generator/2?logoless=true <= like this
Finally I resolved using an attr_accessor called logoless.
Then I create a form with a check_box:
<%= form_for(#legal_vacation, url: request_document_path(id: #legal_vacation.id),
html: { method: "get" }) do |f|%>
<div class="form-row">
<div class="col-8 text-center">
<%= f.submit 'PCF', class: 'btn btn-primary'%>
</div>
<div class="col text-center">
<%= f.check_box :logoless %>
</div>
</div>
<% end %>
And in my controller I take that value to assign it in my pdf's:
def request_document
#legal_vacation= LegalVacation.find(params[:id])
vacation = LegalVacation.new(legal_vacation_params)
#logo = vacation.logoless
if params[:commit] == 'PCF'
document_type = "pcf"
end
pdf_info(document_type)
end
And that all!

Rendering with jquery and locals

Im having trouble rendering with jquery, I have a notification page which shows all notifications, then when i click on 1 for example it will show all the 1's and if i click 2 it will show all the 2's etc etc.
This is where all the notifications are rendered to start with. The locals work fine here.
<% #notifications.each do |x| %>
<div class="testing123">
<%= render 'notification', x: x %>
</div>
<% end %>
Then i click the link to change them
and here is the controller
def index
if params[:type]
#notifications = Notification.where(notification_type: params[:type])
else
#notifications = Notification.all
end
respond_to do |format|
format.html
format.js{
render 'notifications/jserb/select_notifications'
}
end
end
Which then arrives here:
$('.testing123').empty();
$("<%= escape_javascript(render #notifications, :locals => {:x => x}) %>").appendTo(".testing123");
But i keep getting this error
ActionView::Template::Error (undefined local variable or method x' for #<#<Class:0x007fae10882ed8>:0x007fae0f6234b8>):
EDIT-1: here is where i click the link:
<%= link_to "likes", notifications_path, remote: true %>
EDIT-2: here is the notification:
<div class="notification-body flerowspb" id="body<%=x.id%>">
<div class="flerowspb" style="width:80%">
<div class="notif-check flecolcen">
<%= check_box_tag "read_notif[]", value="#{x.id}", checked = false, options = {class: 'checked-id', id: "check-#{x.id}"} %>
</div>
<div class="notif-details ">
<div class="notif-time flerowspb">
<% if !x.viewed %>
<span class="glow" id="glow-<%=x.id%>"> New <%= x.notification_type.capitalize %></span>
<% else %>
<span><span class="text-grey"> New <%= x.notification_type.capitalize %></span></span>
<% end %>
<span class="text-grey font-small"> <%= time_ago_in_words(x.created_at) %> ago</span>
</div>
<div class="notif-body font-medium text-grey">
You have <%= x.status_count %> <%= x.title %> <br>
Click <span class="text-blue"><%= link_to "Here", entry_path(x.entry_id, notification_id: x.id) %> </span> to view it
</div>
</div>
</div>
<div class="notif-image">
<%= image_tag x.entry.image.small_thumb %>
</div>
</div>
EDIT-3: here is the full error that i get:
ActionView::Template::Error (undefined local variable or method `x' for #<#<Class:0x007fae0e6f32b8>:0x007fae11ac1838>):
1: <div class="notification-body flerowspb" id="body<%=x.id%>">
2: <div class="flerowspb" style="width:80%">
3: <div class="notif-check flecolcen">
4: <%= check_box_tag "read_notif[]", value="#{x.id}", checked = false, options = {class: 'checked-id', id: "check-#{x.id}"} %>
Any help will be appreciated
Issue with your code is after click on link it hits the notifications action and where you are getting #notifications as array of notifications, so after this in your js.erb you are rendering appending partial notification.html.erb with local variable x but here at your controller you are getting #notifications variable,
This should be like:
in notifications/_notification.html.erb
<div class="testing123">
<% notifications.each do |x| %>
<%#= render 'notification', x: x %>
#...
<% end %>
</div>
and in notification.js.erb
$('.testing123').empty();
$(".testing123").append("<%= escape_javascript(render 'notifications/notification', notifications: #notifications) %>");

Want to refresh only favorite and not the entire page

Hi there it's the third I ask you to help me on this point.
I don't know how to explain it because I read some tutorials or answers but I don't understand what can I do.
Ok I am working on an app to learn Japanese language with hiragana flashcards.
I created a feature to add a card as a favorite. When I click on a grey color heart, the heart becomes in red color and it saves in an index favs page.
The problem is when I click to add as favorite the full page is loaded and I don't want it. I just wnat have the heart object which changes of state.
I would use ajax and javascript but I don't know what can I call and which is the syntax. I have ever read http://guides.rubyonrails.org/working_with_javascript_in_rails.html
And Try to do the same but it doesn't work.
here is the favs controller
class FavsController < ApplicationController
def index
#favs = Fav.where(user: current_user)
end
def create
#hiragana = Hiragana.find(params[:hiragana_id])
#fav = current_user.favs.new(hiragana: #hiragana)
if not #hiragana.favs.where(user: current_user).take
#fav.save
end
# redirect_to favs_path
# redirect_to :back
render json: #fav
end
def destroy
#fav = Fav.find(params[:id])
#fav.destroy
redirect_to :back
end
end
Above I choose to redirect as a json format but now
here is the render favorite view
<% if current_user %>
<div class="hiragana-fav">
<% if hiragana.is_faved_by(current_user) %>
<%= link_to fav_path(hiragana.is_faved_by(current_user)), method: :delete do %>
<i class="fa fa-heart faved faved-on"></i>
<% end %>
<% else %>
<%= link_to hiragana_favs_path(hiragana), method: :post do %>
<i class="fa fa-heart faved faved-off"></i>
<% end %>
<% end %>
</div>
<% end %>
and the index hiraganas view where the favs render is located
<div class="row">
<ul class="list-inline text-center card-frame">
<li>
<div class="card">
<div class="front">
<% if current_user.try(:admin?) %>
<%= link_to hiragana_path(hiragana), class:'trash-hiragana', data: { confirm: 'Are you sure?' }, method: :delete do %>
<%= image_tag("delete-btn.png") %>
<% end %>
<% end %>
<span class="card-question img-popover" data-content="<h4 class='text-center letter-uppercase'><%= hiragana.bigletter.upcase %></h4><p class='text-center'><b><%= hiragana.midletter %></b> comme dans <b><%= hiragana.transcription %></b></p>">
<i class="fa fa-eye fa-lg"></i>
</span>
<div class="card-hiragana hiragana-<%=hiragana.bigletter.downcase.last%>">
<h1><b><%= hiragana.ideo1 %></b></h1>
</div>
<div class="card-katakana">
<p><%= hiragana.ideo2 %></p>
</div>
<%= render 'favs/favorites', hiragana: hiragana %>
</div>
<div class="back">
<div class="col-sm-3 col-xs-4 col-md-3 containerbackcards-<%=hiragana.bigletter.downcase.last%>">
<div class="backcard-hiragana">
<h1><b><%= hiragana.ideo1 %></b></h1>
</div>
<div class="card-bigletter">
<h4><%= hiragana.bigletter.upcase %></h4>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
I try to call it with this javascript code but i don't where I can place it and how do I have to call the file .js.erb? (I put it in application.js for now but it doesn't communicate with the rest of my code)
application.js
$(document).ready(function() {
$('.faved-on').click(function() {
var fav = $('.faved-off')
$.ajax({
type: "POST",
url: "/hiraganas",
dataType: "json",
success: function(data) {
console.log(data);
},
error: function(jqXHR) {
console.error(jqXHR.responseText);
}
});
})
})
Help will be appreciated :).
Have you tried this: http://guides.rubyonrails.org/working_with_javascript_in_rails.html#link-to ?
There is a simple "remote: true" to add inside your link_to code. Something like that:
<%= link_to hiragana_favs_path(hiragana), class: "add-to-favorite", method: :post, remote: true do %>
<i class="fa fa-heart faved faved-off"></i>
<% end %>
Then to perform some special actions in your Coffee (JS), you could do:
$ ->
$("a.add-to-favorite").on "ajax:success", (e, data, status, xhr) ->
console.log(data)
alert "Favorite added."
And you can do the same thing for the other link_to (the :delete one).
Also I would rather use "button_to" instead of "link_to method: :post" as you did, as "link_to" should not really be used to POST data. Button_to is a simple helper that works like link_to but is replaced by a form, which is better to post data. :)
Of course you don't have to, but it'd be better this way. :)
Let me know if it worked. If not, add comments and edit your question to add more info, I'll try to help you more by editing my answer and adding more info.

Converting a select form to a dropdown buttons

UPDATE: I'm almost there! See my partial answer at the end of this question.
I've got a working form with two select dropdowns, the first for countries, the second for cities. When you select a country, an ajax request automagically gets the countries and updates the countries box.
The problem is the select dropdowns are ugly, and I can't really style them. What I want is a dropdown button, which I can use Bootstrap on to make pretty: Bootstrap Button
I don't have to change the jquery or controller logic, I just have to update my view. But I don't even know where to start. This is what I have:
<%= form_for :trip, url: {action: "index"}, html: {method: "get"} do |f| %>
<%= f.select :country_obj_id, options_for_select(#countries.collect { |country|
[country.name.titleize, country.id] }, #countries.first.name), {}, { id: 'countries_select' } %>
<%= f.select :city_obj_id, options_for_select(#cities.collect { |city|
[city.name.titleize, city.id] }, 0), {}, { id: 'cities_select' } %>
<%= f.submit "Go!" %>
<% end %>
How can I convert the selects into dropdown buttons?
UPDATE: I can now get a response back. I just don't know how to handle it to update the button.
The view has two dropdown buttons. The first is the countries, the second is the cities for the first country. I want to update the list of cities for the country that is selected:
<div class="dropdown" style="display:inline-block;">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Select A Country
<span class="caret"></span></button>
<ul class="dropdown-menu">
<% #countries.each do |country| %>
<%= content_tag(:li, link_to(country.name.titleize, update_cities_path(country_obj_id: country.id), remote: :true)) %>
<% end %>
</ul>
</div>
<div class="dropdown" style="display:inline-block;">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Select A City
<span class="caret"></span></button>
<ul class="dropdown-menu">
<% #cities.each do |city| %>
<%= content_tag(:li, city.name.titleize) %>
<% end %>
</ul>
</div>
Selecting a country goes into the update_cities function, which gets the cities for the country_obj_id that is passed.
def update_cities
#cities = CityObj.where("country_obj_id = ?",
params[:country_obj_id]).order(:name)
respond_to do |format|
format.js
end
end
Then the part that i don't understand. The format.js takes me to update_cities.js.coffee, which I have not changed from my original version that worked on the select dropdown:
$("#cities_select").empty()
.append("<%= escape_javascript(render(:partial => #cities)) %>")
That ends up updating my old select dropdown, which I left in the view for now. But how can I modify the js to update my new dropdown button?
You will need a mix of Javascript with Rails:
First, you will need to print all options in Bootstrap's button format:
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Countries
<span class="caret"></span></button>
<ul class="dropdown-menu">
<% #countries.each do |country| %>
<%= content_tag(:li, country.name.titleize) %>
<% end %>
</ul>
</div>
Add funcionality to select an option from this dropdown:
https://stackoverflow.com/a/22000328/891807
Got it. This is the coolest thing ever. It starts out with two buttons. The first says "Select A Country," and the second says "Select A City." The second button is not active to start with, and I'll probably hide it.
The view:
<div class="dropdown" style="display:inline-block;">
<button id="country-select-btn" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Select A Country
<span class="caret"></span></button>
<ul class="dropdown-menu">
<% #countries.each do |country| %>
<%= content_tag(:li, link_to(country.name.titleize, update_cities_path(country_obj_id: country.id), remote: :true)) %>
<% end %>
</ul>
</div>
<div class="dropdown" style="display:inline-block;">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Select A City
<span class="caret"></span></button>
<ul id="cities_select" class="dropdown-menu">
</ul>
</div>
The dropdown items are just links, with a route set so clicking a link goes to the controller update_cities action with a country passed:
def update_cities
#cities = CityObj.where("country_obj_id = ?",
params[:country_obj_id]).order(:name)
#country = CountryObj.find_by(id: params[:country_obj_id])
respond_to do |format|
format.js
end
end
The format.js goes into update_cities.js
$("#cities_select").empty()
.append("<%= escape_javascript(render(:partial => #cities)) %>")
$("#country-select-btn").empty()
.append("<%= escape_javascript(render(:partial => #country )) %>")
That renders two partials. _city_obj.html.erb renders a link for each of the cities, which will go to the controller's index action when clicked:
<li><%= link_to(city_obj.name.titleize, index_path(:trip => {country_obj_id: city_obj.country_obj.id, city_obj_id: city_obj.id}), id: "cities_select") %></li>
The _country_obj.html partial just updates the "Select A Country" label on the button to the name of the selected country:
<%= country_obj.name.titleize %>
Now, when you click one of the city links, the controller index action can find all the guides for that city/country, then the view will render it.
From what I understood, you want to add style to your html form using bootstrap. If this is the case then this is how you can do that:
1.Add bootstrap gem if you have not done it already following the documentation(https://github.com/twbs/bootstrap-sass)
In short, you need to add following at your Gemfile:
gem 'bootstrap-sass', '~> 3.3.5'
Add following line at your app/assets/stylesheets/application.scss so that bootstrap styles gets added at every page:
#import "bootstrap-sprockets";
#import "bootstrap";
2.Using bootstrap styles, at your ugly select tag you need to add form-control at your class name as bootstrap documentation suggests. add class: "form-control" parameter like this:
<%= form_for :trip, url: {action: "index"}, html: {method: "get"} do |f| %>
<%= f.select :country_obj_id, options_for_select(#countries.collect { |country|
[country.name.titleize, country.id] }, #countries.first.name), {}, { id: 'countries_select', class: "form-control" } %>
<%= f.select :city_obj_id, options_for_select(#cities.collect { |city|
[city.name.titleize, city.id] }, 0), {}, { id: 'cities_select', class: "form-control" } %>
<%= f.submit "Go!" %>
<% end %>

Rails: 'Load More' button with Ajax & Kaminari

I would like to create a "load more" ajax pagination, with Kaminari.
I'm using this code :
class BienvenueController < ApplicationController
def index
#articles = Admin::Article.page(1).per(2)
respond_to do |format|
format.html
format.js
end
end
end
# Bienvenue#index
<div class="container" style="min-width:<%= #width %>px">
<%= render "shared/articles" %>
<%= link_to_next_page #articles, 'Load More', :remote => true, :id=>"load_more_link" %>
# Shared/articles
<% #articles.each do |a| %>
<article class="<%= a.rubrique.color %>">
<div class="sharing">
<%= image_tag "facebook-32.png" %>
</div>
<p class="color<%= a.rubrique.color %>"><i>Le <%= I18n.localize(a.created_at, :format => :long) %> par David Perrotin</i></p>
<h1><%= a.titre %></h1>
<div class="excerpt">
<%= a.chapo.html_safe %>
</div>
<div class="image">
<%= image_tag a.mainphoto.url(:medium), :width=>"100%" %>
</div>
<div class="contenu">
<%= a.contenu.html_safe %>
</div>
<div class="readmore">
<%= link_to "Continuer la lecture", article_path(a) %>
</div>
</article>
<% end %>
# index.js.erb
$('.container').append("<%= escape_javascript(render 'shared/articles')%>");
$('#load_more_link').replaceWith("<%= escape_javascript(link_to_next_page(#articles, 'Load More', :remote => true, :id=>'load_more_link'))%>");
But the problem is that when I click on "Load More", it always shows the two same articles, the partial is never refreshed with two more articles, like I would like.
I just ran into an issue with this that might help others. Depending on your version of jQuery, don't use replaceWith on the #load_more_link in index.js.erb.
There is a regression (http://bugs.jquery.com/ticket/13401) that an empty replaceWith does nothing, so on the very last page of your set, the link_to_next will be empty, making the line: $('#load_more_link').replaceWith(''); and thus will not replace the last "more" button, so you'll continually load the last page of your data set.
Fixed by updating jQuery version or use empty().html('...') instead of replaceWith.

Resources