Refresh a div when a user signs in via ajax? - javascript

I currently have a <ul> in my navigation area which holds a <%= render :partial => "sessions/manager" %> which basically calls another partial which depending on the users login status renders either a login form or a welcome statement.
My login section is powered by ajx and so refreshes automaticlly. Here's the code im using.
login.js
$(document).ready(function() {
$('form#sign_in').bind('ajax:success', function(e, data, status, xhr) {
console.log(data);
if(data.success) {
$('.user_nav').html(data.content);
} else {
$('.user_nav').prepend(data.errors.join('<br />'));
}
});
});
Now I want another div on my page containing various links to either hide or show depending on the users logged in status.
Currently my code is this.
<% if(signed_in?) %>
<li><%= link_to "Clients", "/clients" %></li>
<li><%= link_to "Jobs", "/jobs" %></li>
<% else %>
<% end %>
However, this doesn't work how id like. The links don't show at first which is cool BUT the links don't show again when im signed in... unless I do a full page refresh.
How can I ajax-ify this section?

The easiest thing is to put the divs on the page and then set toggle their visibility with javascript.
Put this in your code:
<li class="login-show" <%= signed_in? ? "" : "style='display:none'" %> >
<%= link_to "Clients", "/clients" %>
</li>
<li class="login-show" <%= signed_in? ? "" : "style='display:none'" %> >
<%= link_to "Jobs", "/jobs" %>
</li>
And then this is your js:
$('form#sign_in').bind('ajax:success', function(e, data, status, xhr) {
console.log(data);
if(data.success) {
$('.user_nav').html(data.content);
// show the li items hidden from non-logged in users
$('.login-show').show();
} else {
$('.user_nav').prepend(data.errors.join('<br />'));
}
});
});
That should work. but to keep things really tidy, I would move this junk:
<%= logged_in? "" : "style='display:none'" %>
into a helper method

Related

Rails 5, simple javascript with form submit

I am hoping someone can help me here. Been at this for a few hours, but can't seem to figure out why my Javascript is not working on my simple form. I'm simply trying to display comments using the ajax call. I have gem 'jquery-rails', and required jquery, and jquery_ujs in my application.js file. Here's the code I have so far:
I have a Joy model that has_many comments.
<% #joys.each do |joy| %>
<ul id="comments-<%= joy.id %>">
<% joy.comments.where(void:'f').each do |comment| %>
<li><%= comment.body %></li>
<% end %>
</ul>
<%= form_with(model: [ joy.user, joy, joy.comments.build ], data:{ "js-comments-#{joy.id}" => true}) do |f| %>
<%= f.text_area :body, :class=>'form-control', :required=>'true' %>
<%= f.submit "Post Comment" %>
<% end %>
<script>
$(document).ready(function() {
$('[data-js-comments-<%= joy.id %>]').on("ajax:success", function(event, data, status, xhr){
$('#comments-<%=joy.id%>').append(xhr.responseText);
});
});
</script>
<% end %>
In my Comment controller, in my 'create' action, I have:
if #comment.save
render partial: "comment", locals: {comment: #comment}
end
In my Comment views, I created a partial, called _comment.html.erb:
<li>
<%= comment.body %>
</li>
So, now when I enter a comment, and click 'Post Comment', it correctly saves my Comment, but it does not ajax load the comment into list. Furthermore, the form does not refresh either. The text remains in the text box. It is not only until after I refresh the page when my comment shows up in the list. Anyone with any thoughts on what I'm missing or doing wrong???
Your help is greatly appreciated in advance.
form_with it's a remote form, you dont need that block <script>..</script>.
Just use create.js.erb then use jquery to append new comment.
And if you want to check if your message was created successfully, you can add a #status value in your controller.
//comments_controller.rb
def create
...
if #comment.save
#status = "success"
else
#status = "failed"
end
...
end
//create.js.erb - for example
$("#yourCommentList").append('<%= j( render partial: 'comments/comment', locals: #comment ) %>');
<% if #status == "success" %>
$("body").append(...your notification...)
...
<% else %>
...
<% end %>

Using JavaScript/Jquery to show forms with the same id/class in Ruby

I want to have a button for retweets in my web-application. When I press the button I want a form to display in order to add my own text to the tweet.
I implemented this . However I have a problem: all my forms and buttons contain the same id and class, so you can imagine that when I press a button it will display the first form with that id/class instead of the one that it has to show. How can I show the form that I have to show ?
Here are only the parts of the code that contain retweet part(the other parts are not important I think for the problem but I can post them if someone wants me to) :
<button type="buton" id="retweet-button">retweet</button>
<%= form_for(current_user.tweets.build,url: retweet_act_path, method: :post, html: { multipart: true, :class => "retweet_form" }) do |f| %>
<%= f.hidden_field :original_tweet_id, value: tweet.id %>
<%= f.text_area :content, placeholder: "Add a message to the tweet..." %>
<%= f.submit "Retweet"%>
<% end %>
And the JS:
<script type="text/javascript">
$(document).ready(function() {
$('.retweet_form').hide(); //Initially form wil be hidden.
$('#retweet-button').click(function() {
$('.retweet_form').show();//Form shows on button click
});
});
</script>
How can I show the form that I have to show when pressing a certain button ? (I guess I have to have a different ID for every button and form , but how ? )
As I understood from the code, you use one button/form pair per tweet. So that, you are able to use tweet ID to generate form ID. To connect button to appropriate form, use data-* fields.
Generation of forms and buttons on Rails side (NOTE: syntax highlight is broken):
<button type="button" class="retweet-button" data-target-form-id="<%= "#retweet-form-#{tweet.id}" %>">retweet</button>
<%= form_for(current_user.tweets.build,url: retweet_act_path, method: :post, html: { multipart: true, :class => "retweet_form", id: "retweet-form-#{tweet.id}" }) do |f| %>
<%= f.hidden_field :original_tweet_id, value: tweet.id %>
<%= f.text_area :content, placeholder: "Add a message to the tweet..." %>
<%= f.submit "Retweet"%>
<% end %>
And JS:
$('.retweet_form').hide();
$('.retweet-button').click(function() {
var formId = $(this).data('target-form-id');
$(formId).show();
});

how to make collection_select value as link_to variable

I have the ff:
app/views/reports/index.html.erb
<h1>Reports</h1>
<br>
<legend>Categories</legend>
<div class="row">
<div class="span5">
<ol>
<li><%= link_to 'COMMENDATION', commendations_path(format: 'pdf'), { id: 'commendations_click' } %></li>
<%= collection_select(nil,
:employee_id,
#employees,
:id,
:last_name,
{:prompt => "Select an Employee"},
{:id => 'employees_select'}) %>
<br>
<%= collection_select(nil,
:employee_movement_id,
#employeemovements,
:id,
:position,
{:prompt => "-"},
{:id => 'employee_movements_select'}) %>
<li><%= link_to 'REPORT2', '#' %></li>
<li><%= link_to 'REPORT3', '#' %></li>
</ol>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#employees_select').change(function() {
$.ajax({
url: "<%= update_employee_movements_path %>",
data: { employee_id : $('#employees_select').val() },
dataType: "script"
});
});
$('#commendations_click').click(function() {
$.ajax({
url: "<%= commendations_path %>",
data: {
employee_id : $('#employees_select').val(),
employee_movement_id : $('#employee_movements_select').val()
},
dataType: "script"
});
});
});
</script>
app/controllers/reports_controller
class ReportsController < ApplicationController
before_filter :authenticate_user!
# GET /reports
def index
#employees = Employee.all
#employeemovements = EmployeeMovement.distinct_positions
end
def update_employee_movements
if params[:employee_id]
#employeemovements = [].insert(0, "Select Employee Movement")
else
employee = Employee.find(params[:employee_id])
#employeemovements = employee.employee_movements.map{ |a| [a.position, a.id] }.insert(0, "Select Employee Movement")
end
end
def commendations
emdates = EmployeeMovement.last_2_dates_obtained(params[:employee_movement_id])
date_from = emdates[0].date_obtained
date_to = emdates.length == 1 ? nil : emdates[1].date_obtained
emp = Employee.find(params[:employee_id])
#commendations = case date_to.nil?
when true then emp.commendations.this_day_onwards(date_from)
else emp.commendations.within(date_from, date_to)
end
end
end
What I'm trying to do here is, I'm creating a page filled with links and drop down lists that will serve as a Reports center. The idea is, each link will be catered by a controller. Each controller will be responsible in showing my PDF in the browser (through ThinReports, if you're curious).
The #employees_select change event is used for changing the value of the #employee_movements_select collection_select.
Now my problem is, how can i capture the value of both #employees_select and #employee_movements_select and pass them to my commendations action?
I tested link_to by hardcoding values, and it works (code below)
<%= link_to 'COMMENDATION', commendations_path(employee_id: 1, employee_movement_id: 12, format: 'pdf') %>
However, If I use javascript to push the values to my commendations action through the 'click' event, my commendations action will be called twice, thus an error occurs because the params[:employee_id] in the action is now blank.
By the way, I need those values because my commendations action needs it so I can populate my PDF report template.
Please help. Thanks a lot in advance!
UPDATE 1
-> Updated link_to:
<%= link_to 'COMMENDATION', '#', { id: 'commendations_click' } %>
-> Removed dataType: "script" in #commendations_click event handler
-> Updated url: in #commendations_click event handler
url: <%= commendations_path(format: 'pdf') %>
UPDATE 2 (RESOLUTION)
I tweaked my javascript to look something like this:
$('#commendations_click').click(function() {
event.preventdefault();
window.location = "<%=j commendations_path(format: 'pdf') %>" + "?employee_id=" + $('#employees_select').val() + "&employee_movement_id=" + $('#employee_movements_select').val();
});
Works perfect now.
Two things come to mind. You can wrap the two select lists within a form element and just do a submit. Everything inside the form will be submitted to your server and you can process the request and handle the redirect on the server side. The other thing you can do is to handle the commendations click event on the client side using jquery or something. Just bind to the click event of that link, grab the values of the two select lists and do whatever you want with it. Remember, link_to just gets rendered as plain old html links on the view. For e.g.
link_to "Profile", profile_path(#profile) gets rendered as Profile

Rails 3 - Checkbox dependant of radio button selection

I need a solution to hide/show a checkbox depending a radio button selection. I tried different solution found here and there but I can make them work.
CONTEXT:
I have a pool of contact persons that can be associated to a business. A user can select multiple contact persons but MUST select a primary contact person. So I have a radio button group whit all the contact persons to select the primary contact, and I have a checkbox group with again all the contact persons to select the "other" contacts.
NEED:
Now, what I like to do is that when the user select the primary contact in the radio button group, this contact will be removed from the "other contact" checkbox group, so the user cannot select the same contact twice. I can use JQuery as well as plain JavaScript.
CONSTRAINT:
The radio button group, as well as the checkbox group, are dynamically created using Rails Tag helper. So it's kind of tricky for the ids and name of the elements. Also, there is a has_many :trough between business and contact.
So for the radio button, I have:
<% #contacts.each do |contact| %>
<li><%= radio_button_tag 'primary_contact', contact.id, #primary_contact == contact, :class => 'radio'%> <%= contact.name %>, <%= contact.contact_type.name %></li>
<% end %>
And for the checkbox group, I have:
<%= hidden_field_tag 'business[contact_ids][]', "" %>
<% #contacts.each do |contact| %>
<li><%= check_box_tag 'business[contact_ids][]', contact.id, #business.contacts.include?(contact), :class => 'radio' %> <%= contact.name %>, <%= contact.contact_type.name %></li>
<% end %>
Any suggestion about other design (using radio buttons and checkboxes...) to achieve my goal are very welcome.
Thanks
Alain
<li><%= radio_button_tag ... :id => "#{contact.id}", :onclick => 'removeFromOtherList(this.id);' %><%= " #{contact.name}, #{contact.contact_type.name}" %></li>
This way you have the contact ids for the HTML tag id. Onclick it will remove\disable the other contact
Do the same for the other contacts
...<%= check_box_tag ... :class => 'radio', :id => "otherContact#{contact.id}" %> ...
Then we can remvoe the correct contact from the other list
function removeFromOtherList(contactId) {
$("#otherContact"+contactId).parent().remove(); //to remove the LI
}
Demo
Edit:
One way to do it is use show/hide and keep track of the last selected radio
var lastSelectedRadioId = null;
function removeFromOtherList(contactId) {
$("#otherContact"+contactId).parent().hide();
if(lastSelectedRadioId ){
$("#otherContact"+lastSelectedRadioId ).parent().show();
}
lastSelectedRadioId = contactId;
}
Demo

JS and Rails site wide announcements

Tried doing http://davidwparker.com/2008/09/17/site-wide-announcements-in-rails-using-jquery-jgrowl/
Am really bad with JS. Think I am messing up on the last part where it says "This code goes in your application.js file (somewhere in $(function){ //here })"
Am I not suppose to do a link_to_function and create a function with this code that references that link?
Really lost on this one.
Updated -
application.js looks like
$(document).ready(function() {
$.jGrowl.defaults.closer = true;
$("#announcements_box").css("display", "none");
$("#announcements_box .announcement").each(function(){
$jQuery.jGrowl(this.textContent,{ sticky:true, close:function(e,m,o){hide_announcements();} });
});
});
function hide_announcements(){
$.get(
'/hide_announcements'
);
$("#announcements_box").fadeOut();
return false;
}
And my application.html.erb has
<% unless current_announcements.empty? %>
<div id="announcements_box">
<% for announcement in current_announcements %>
<div id="announcement_<%= announcement.id.to_s %>" class="jGrowl">
<%= announcement.message %>
<%= link_to "Hide Annoucements", hide_announcements_path, :id => 'hideAnn'%>
</div>
<% end %>
</div>
<% end %>
I'm not sure what $(function){ //here } notation means, that should give you error in the browser, but I think he just wants to execute code after page is loaded:
$(document).ready(function() {
// here
}
And the culprit was I only entered a div ID when I needed to have a div ID and class.

Categories

Resources