Form select option to change what gets rendered - javascript

Ruby on Rails 4 form with a drop down selection. If Multiple Choice is selected I want to render a page. If True/False is selected I want to render a different page.
I do not know why this isn't working, My javascript knowledge is bad:
<h1>New question</h1>
<%= form_for(#question) do |f| %>
<%= render 'shared/error_questions' %>
<%= render 'form', f: f %>
<%= f.fields_for :answers do |builder| %>
<div id="mcanswers" style="display:none">
<h1>Answers</h1>
<%= render 'four_answers', :f => builder %>
<%= f.submit "Create Question", class: "btn btn-lg btn-primary" %>
</div>
<div id="tfanswers" style="display:none">
<h1>Answers</h1>
<%= render 'tf_answers', :f => builder %>
<%= f.submit "Create Question", class: "btn btn-lg btn-primary" %>
</div>
<% end %>
<% end %>
<hr />
<%= link_to 'Back', questions_path %>
<script>
function checkType() {
if ($('#question_question_type').val('MC'))
{
$('#mcanswers').css('display', 'block');
}
else if ($('#question_question_type').val('TF'))
{
$('#tfanswers').css('display', 'block');
}
}
$(document).ready(function() {
$('select#question_question_type').on('change', function() {
checkType();
});
});
</script>

Everything is rendered from the beginning. The div is just hiding it. I had to use controller logic to decide when to render.

Related

Using ajax to change the state of a button in Ruby on Rails views

I have a setting in which I would like to dynamically change a buttons disabled state. Currently the logic I have looks as follows:
<% if #has_attachment_file_sent %>
<% if current_user.id != #offer.user_id %>
<%= link_to send_signature_requests_path, remote: true, method: :post,
data: { confirm: "Are you sure?" },
id: "signature_request_button",
class: "button is-info is-fullwidth m-t-10 m-b-10" do %>
<span>Send request</span>
<% end %>
<% end %>
<% else %>
<button class="button is-info is-fullwidth m-t-10 m-b-10" disabled>Send request</button>
<% end %>
However, the problem with this method is that this only changes the state of the button when you refresh the page. Is there a way to do this kind of Ajax with RoR or what should I do here?
Also tried using javascript as follows:
<script>
$(document).ready(function() {
var has_attachment_file_sent = <%= #has_attachment_file_sent %>
console.log(has_attachment_file_sent);
if(has_attachment_file_sent) {
$('#signature_request_button').attr('disabled', true);
}
})
</script>
but this doesn't seem to be doing anything.
Also here's my controller
def show
#offer = Offer.find(params[:id])
#has_attachment_file_sent = Comment.where(user_id: #offer.user_id).any? {|obj| obj.attachment_file.attached?}
respond_to do |format|
format.html
format.js { render layout: false, content_type: 'text/javascript' }
end
end
First place your html in a partial and wrap the content in div, assume that the partial's name is 'buttons.html.erb'
_buttons.html.erb
<% if #has_attachment_file_sent %>
<% if current_user.id != #offer.user_id %>
<%= link_to send_signature_requests_path, remote: true, method: :post,
data: { confirm: "Are you sure?" },
id: "signature_request_button",
class: "button is-info is-fullwidth m-t-10 m-b-10" do %>
<span>Send request</span>
<% end %>
<% end %>
<% else %>
<button class="button is-info is-fullwidth m-t-10 m-b-10" disabled>Send request</button>
<% end %>
<div id="buttons">
<%= render partial: 'buttons' %>
</div>
Add button in view
<%= link_to 'Refresh', show_page_path(id: #offer.id), id: 'btn_call_ajax', remote: true %>
you should adapt show_page_path with your route
def show
#offer = Offer.find(params[:id])
#has_attachment_file_sent = Comment.where(user_id: #offer.user_id).any? {|obj| obj.attachment_file.attached?}
respond_to do |format|
format.html
format.js
end
end
Then you should create a file named show.js.erb that contain the following code:
$('#buttons').html('')
$('#buttons').append("<%= escape_javascript render(:partial => 'buttons') %>");
Oh yeah, how annoying, forgot about that
Maybe something like this inside js.erb
It should work, hacks but I’m sure there is another solution I’m going blank on
# render partial line here
<% if #disabled %>
$(‘#button-id’).prop(“disabled”, true);
<% else %>
$(‘#button-id’).removeAttr(“disabled”)
<% end %>
create the file show.js.erb and in your controller just leave it as format.js without curly braces.
create a partial with
<button class="button is-info is-fullwidth m-t-10 m-b-10" disabled="<%= disabled ? “disabled” : “” %>”>Send request</button>
And add a div in original file, wrap rendering of the partial above
<div id=“woohoo”>
<%= render partial: “file_above”, locals: {disabled: true} %>
</div>
Then in that .js.erb file add this $(‘#div-around-button’).html(“<%= j render(‘show’, disabled: #disabled_variable_from_controller) %>”) and it will basically refresh that button with new value that you got from controller 🙂
P.S. I wrote this all on my iPhone so I might have missed small things like syntax

Triggering a click through Jquery on ruby code

So I'm trying to get my f.submit to be triggered when I click f.check_box. I don't know if you can use jquery to work on ruby... But basically this is a view of a to-do list with all the items on the page. When I click the checkbox to mark it off, I want it to be automatically submitted.
I thought I could assign a div tag on the f.check_box and the f.submit to trigger them... This is the first bit of JQuery I've working with.
<h1><%= #list.title %></h1>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<div>
<h2><% #list.items.each do |item| %></h2>
<%= item.content %>
<%= form_for([#list, item]) do |f| %>
<div id="target">
<%= f.check_box :complete %>
</div>
<div id="handler">
<%= f.submit %>
<% end %>
</div>
<% end %>
</div>
<script>
jQuery(document).ready(function() {
jQuery("#target").click(function() {
jQuery("#handler").click();
});
});
</script>
<% if policy(#list).update? %>
<%= link_to "Edit List", edit_list_path, class: 'btn btn-success' %>
<% end %>
<div class="col-md-4">
<% if policy(Item.new).create? %>
<%= link_to "New Item", new_list_item_path(#list), class: 'btn btn-success' %>
<% end %>
<% if policy(#list).destroy? %>
<%= link_to "Delete List", #list, method: :delete, class: 'btn btn-danger', data: { confirm: 'Are you sure you want to destroy this lovely list?'} %>
<% end %>
</div>
</div>
<%= render "items/form" %>
<!--
new_list_item_path
/lists/5/items/new
-->
div does not fire onclick event you need to set onchange method of checkbox which will submit the form.
Here is a code for that.
You need to set different id for every submit-button and then you can submit that form using Jquery.
I set the onchange method of checkbox which submits that forms according to item id.
<h1><%= #list.title %></h1>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<div>
<%index=0%>
<h2><% #list.items.each do |item| %></h2>
<%= item.content %>
<%= form_for([#list, item]) do |f| %>
<%=f.check_box :complete,{:onchange=> "submit_form("+#list.items[index].id.to_s+");"}%>
<%= f.submit :id=>#list.items[index].id%>
<%index+=1%>
<% end %>
<% end %>
</div>
<% if policy(#list).update? %>
<%= link_to "Edit List", edit_list_path, class: 'btn btn-success' %>
<% end %>
<div class="col-md-4">
<% if policy(Item.new).create? %>
<%= link_to "New Item", new_list_item_path(#list), class: 'btn btn-success' %>
<% end %>
<% if policy(#list).destroy? %>
<%= link_to "Delete List", #list, method: :delete, class: 'btn btn-danger', data: { confirm: 'Are you sure you want to destroy this lovely list?'} %>
<% end %>
</div>
</div>
<%= render "items/form" %>
<script>
function submit_form(id) {
$('#'+id).click();
}
</script>
Um, try something like:
$("input[type=checked]").on("click", function() {
if( $(this).is(':checked') ) { $('form').submit() }
}
And you might want to
<%= f.check_box :complete, html: { class: "check_complete"} %>
and
<%= f.submit, ".." id: "handler"%>
And then replace replace the input[type=checked] with .check_complete and maybe use the ("#handler").click(); instead of .submit()

Button doesn't update in Ajax on Users Index page - Rails Tutorial 4

TLDR: Trying to add a follow/unfollow button to the Users#Index action but when clicking on the button nothing happens.
I have followed Michael Hartl's Rails Tutorial app and now that it's complete I want to add extra functionality for the Follow/Unfollow button. Currently, you can only follow/unfollow a user after visiting their profile page thru the Users Show action. I've attempted to expand this functionality to the Index page of the Users controller so that instead of having to visit each user's profile page in order to follow/unfollow them, a follow button will also appear next to their name in the Index view.
The code that works initially for the follow/unfollow button on the Users Show action:
users_controller.rb
https://gist.github.com/anonymous/9602598
show.htlm.erb for users view
https://gist.github.com/anonymous/9602616
_follow_form.htlm.erb partial for users view
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
_follow.html.erb partial for users view
<%= form_for(current_user.relationships.build(followed_id: #user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
_unfollow.html.erb partial for users view
<%= form_for(current_user.relationships.find_by(followed_id: #user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
create.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
index.html.erb inside of the users view
<%= render #users %>
_user.html.erb partial inside of users view
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
I've tried a few different approaches that so far have been fruitless
First I tried simply rendering the follow_form partial inside of the _user partial just like it's done for the User Show view
_user.html.erb partial inside of users view
<%= render 'follow_form' if signed_in? %>
this resulted in the following error: NoMethodError in Users#index "undefined method `id' for nil:NilClass" and it hilights the following line of code inside of the follow_form partial
<% if current_user.following?(#user) %>
After mucking around with the variables and the controller for a few hours I finally managed to get the buttons to show properly on the index page with the following code inside of the _user.html.erb partial
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(#current_user.relationships.find_by(followed_id: #users),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: #users),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
This code however, only shows the correct follow/unfollow buttons for each user but when you click a button nothing happens. I also attempted to edit the JS files with the following code
create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#user").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#user").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
This didn't have any effect.
The more I tinker with different parts of the code the more it's confusing me. Here is my relationships controller for good measure.
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
I know it's alot but if anyone can help shed some light on my situation I would be very grateful. This is my first venture outside of tutorials and I figured it would be a good idea to try and add features to an already working project instead of start something from scratch.
Just in case anybody was on this question and was still looking for the correct Ajax code. This works with the existing controller and nothing else will have to be changed.
create.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/unfollow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
destory.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/follow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
_user.html.erb
<div class="col-md-2">
<% unless current_user?(user) %>
<% form_id = user.id.to_s %>
<div id="follow_form_<%= form_id %>">
<% if current_user.following?(user) %>
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
<% else %>
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
</div>
This is my first post. Yay! Hope it helps someone!
Use the following code in _user.html.erb partial:
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
I made couple of changes to the code in form_for method call in 2 places:
#current_user should be current_user.
Secondly, followed_id: #users should be followed_id: user.id

has_many and accepts_nested_attributes_for with nested forms and jquery/ajax

I'm trying to create a nested form where there is a "+" button which adds fields via jquery and ajax. I am doing it adding a step at once, so untill now I am able to add a simple text pushing the "+" button, but, as I have just said, I want to add some fields.
I have the followings:
new.html.erb
<h1>New Campaign</h1>
<%= form_for #campaign, html: { multipart: true } do |f| %>
....
<div class="goods">
<%= render "goods/good", f: f, child_index: Time.now.to_i %>
</div>
<div class="actions">
<%= link_to '+', add_good_row_path(params[:campaign]=#campaign, params[:f] = f), remote: true, class: 'btn btn-large btn-success' %>
<%= f.submit 'Crea', class: 'btn btn-large btn-warning' %>
</div>
<% end %>
goods/_good.html.erb
<%= f.fields_for :goods, #campaign.goods.build, child_index: child_index do |good| %>
<%= good.text_field :name, placeholder: 'Nome' %>
<%= good.text_area :description, placeholder: 'Descrizione' %>
<%= good.text_field :cost, placeholder: 'Costo' %>
<% end %>
campaigns_controller.rb
class CampaignsController < ApplicationController
....
def add_good_row
respond_to do |format|
format.js
end
end
end
add_good_row.js.erb
$('.goods').append("hello");
I think that I understood the problem, it is to pass a f variable, a #campaign variable and a child_index to the partial, but how can I do that via jquery?
Hope I was clear...
Have a look at this gem.
I think it's what you are looking for
https://github.com/nathanvda/cocoon

How do I apply function to just the class a jquery ajax submission was done from?

Here is the code I'm currently using:
$.ajax({
success: function(){
$('.post_container').append('test <br />');
}
});
<% sleep 1 %>
It is similar to the code I used for my single main micropost form but with this there are several comments that use the same class and so test is being applied to all post_containers rather than the one the post was just made to. "test" text will eventually be replaced with the div that holds the actual comments users post.
Normally I would use "this" but that won't work here.
HTML:
<div class="post_content">
<div class="post_container">
<div class="userNameFontStyle">
<%= link_to current_users_username.capitalize, current_users_username %> -
<div class="post_time">
<%= time_ago_in_words(m.created_at) %> ago.
</div>
</div>
<%= simple_format h(m.content) %>
</div>
<% if m.comments.any? %>
<% comments(m.id).each do |comment| %>
<div class="comment_container">
<%= link_to image_tag(default_photo_for_commenter(comment), :class => "commenter_photo"), commenter(comment.user_id).username %>
<div class="commenter_content">
<div class="userNameFontStyle">
<%= link_to commenter(comment.user_id).username.capitalize, commenter(comment.user_id).username %> - <%= simple_format h(comment.content) %>
</div>
</div>
<div class="comment_post_time">
<%= time_ago_in_words(comment.created_at) %> ago.
</div>
</div>
<% end %>
<% end %>
<% if logged_in? %>
<%= form_for #comment, :remote => true do |f| %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :micropost_id, :value => m.id %>
<%= f.text_area :content, :placeholder => 'Post a comment...', :class => "comment_box", :rows => 0, :columns => 0 %>
<div class="commentButtons">
<%= f.submit 'Post it', :class => "commentButton" %>
<div class="cancelButton">
Cancel
</div>
</div>
<% end %>
<% end %>
</div>
</div>
How would I deal with this?
Kind regards
NEW:
$(function() {
$('.post-form').submit(function(){
var $post_content = $(this).find('.post_content');
$.ajax({
url: this.attributes['action'],
data: $(this).serialize(),
success: function() {
$post_content.append('test <br />');
}
})
return false; //this will stop the form from really submitting.
});
});
This should do what you're looking for. Simply include this javascript anywhere.
OLD:
$('form').submit(function(){
$.ajax({
url: this.attributes['action'],
data: $(this).serialize(),
//the below line might need to be adapted.
var post_content = $(this).find('.post_content');
success: function() {
$(post_content).append('test <br />');
}
})
this assumes that there is only one form on the page. However, for the code to completely work, I need to know how to differentiate which .post_content is the "submitted" post_content. How do you programatically determine that? Is there a different button for each post_content? Or are there different forms around each post_content div? Whichever way it is, you'll have to include that somehow into the js code.
This is how I had to do it in the end.
.new_comment is my form id
$('.new_comment').on('ajax:success', function(){
$(this).parent('.post_content').find('.comment_container:last').after("<BR />TEST <BR />");
});
<% sleep 1 %>
The only issue now is identifying the actual comment_container for the post just made.

Categories

Resources