Rails 3 coffeescript controller association? - javascript

Alright, I'm a JS / JQuery / Coffeescript noob. This is probably easy points for someone.
Having successfully implemented RBate's Nested Form Model railscast, I am attempting to reproduce this in a simpler model: Chapters have many counties.
I have a chapters.js.coffee file with the following code:
jQuery ->
$('form').on 'click', '.remove_fields', (event) ->
$(this).prev('#destroy').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()
This code works just fine in the other model. But not here.
_chapters_form.html.erb:
<div class="row span12">
<%= form_for(#chapter) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="span2"><strong>Chapter name:</strong></div>
<div class="span6"><%= f.text_field :name %></div>
<div class="span2"><strong>Chapter Number:</strong></div>
<%= f.number_field :chapter_num, class: "span2" %>
</div>
<div class="row span12">
<div class="span12">
<%= f.fields_for :counties do |builder| %>
<%= render 'county_fields', f: builder %>
<% end %>
</div>
<% if f.object.new_record? then link = 'Add the Chapter' else link = 'Update Chapter' end %>
<%= f.submit "#{link}", class: "btn btn-large btn-primary" %>
<%= link_to "Cancel", chapters_path, class: "btn btn-large btn-primary" %>
<% end %>
</div>
and:
_county_fields.html.erb:
<fieldset>
<div class="well span12">
<div class="row span12">
<div class="span3">County Number: <br /><i>(6-digit FIPS code)</i></div>
<div class="span2"><%= f.number_field :county_num %></div>
<div class="span2">County Name:</div>
<div class="span5"><%= f.text_field :name %></div>
</div>
<div class="row span12"><hr></div>
<div class="row span12">
<div class="span6">Move to new Chapter:</div>
<div class="span6"><%= select(:county, :chapter_id, Chapter.all.collect {|c| [c.name, c.id]}) %></div>
</div>
<div class="row span12">
<div class="pull-right">
<%= f.hidden_field :_destroy, id: "destroy" %>
<%= link_to "remove county", "#", class: "remove_fields" %>
</div>
</div>
</div>
</fieldset>
There are no errors in the JS. Again, noob speaking, but it doesn't seem that the JS is getting called. Clicking <%= link_to "remove county", "#", class: "remove_fields" %> just adds the # to the URI.
What am I doing wrong?
As requested, the HTML in a fiddle which doesn't work either.

Your HTML is broken. You open a div before the form element, then close it before you close the form. If you move the form element up to just inside the container div, it works.
<body>
<div class="container-fluid">
<form accept-charset="UTF-8" action="/chapters/7" class="edit_chapter" id="edit_chapter_7" method="post">
<div class="row-fluid">
...
</div>
</form>
</div>
</body>
You should take more care in the indenting of your HTML to help avoid this sort of simple mistake. Code format matters.

The page on which they appear - regardless of how they are rendered - must be an action of the chapters_controller for chapters.js.coffee to be included. My bet is that the script is not being included at all, as the code looks fine. Check out the pages you are having issues with with this code:
jQuery ->
console.log "included chapters.js.coffee"
$('form').on 'click', '.remove_fields', (event) ->
console.log "clicked .remove_fields"
$(this).prev('#destroy').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()
Also, post up the rendered HTML in your question

Related

Ruby on Rails on rendering with Ajax

I am working on a simple website which has posts in forms of songs, now I have implemented like and dislike feature, but when I click on like/dislike it renders the numbers of likes/dislikes on all posts. And when I reload the page it returns them to normal. Now I would like it to change only the numbers for that particular post, without affecting the numbers on other posts?
My view for posts:
<div class="col-6">
<% for #s in #songs %>
<div class="card border-secondary mb-1">
<div class="card-header">
<div class="col-1">
<%= image_tag User.find(#s.user_id).user_image.url, :size=>"50x50" %>
</div>
<div class="col-11 text-muted">
<a href="/user/<%= User.find(#s.user_id).username %>" class="info-col">
<%= User.find(#s.user_id).username %>
</a>
- <%= #s.created_at.to_formatted_s(:short) %>
</div>
</div>
<div class="card-body">
<h4 class="card-title">
<%= #s.title %>
</h4>
<p class="card-text"><%= simple_format(#s.content) %></p>
</div>
<div class="card-footer text-muted">
<div class="col-12">
<div class="row">
<div class="col-3" id="song_like">
<%= render '/components/song_like' %>
</div>
<div class="col-3" id="song_dislike">
<%= render '/components/song_dislike' %>
</div>
<div class="col-4" id="song_comment">
<%= render '/components/song_comment' %>
</div>
</div>
</div>
</div>
</div>
<% end %>
</div>
The song_like partial has the following code:
<%= link_to like_song_path(#s.id, like: true), remote: true, method: :post do %>
<i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <span class="songlikes">
<%= #s.thumbs_up_total %>
</span>
<% end %>
The song_dislike partial has the following code:
<%= link_to like_song_path(#s.id, like: false), method: :post, remote: true do %>
<i class="fa fa-thumbs-o-down fa-lg" aria-hidden="true"></i> &nbsp <span class="songdislikes">
<%= #s.thumbs_down_total %>
</span>
<% end %>
And my 'like' controller is like:
def like
#s = Song.find(params[:id])
#like = Like.create(like: params[:like], user: current_user, song: #s)
respond_to do |format|
if #like.valid?
format.html
format.js
else
format.html
format.js
end
end
end
This is how like.js.erb looks like:
$('.songlikes').html("<%= #s.thumbs_up_total %>");
$('.songdislikes').html("<%= #s.thumbs_down_total %>");
Here is the part of routes.rb file:
resources :songs do
member do
post 'like'
end
end
I am assuming there is some issue on rendering or jquery, but can't figure it out. Do You have any instructions?
EDIT: You should remove the redirect_to in your f.html?
This reloads the page - and the js will therefore not work.
An Ajax call is per definition not reloading the page.
If you remove those lines and try the following:
There's no new data in your jQuery.
You need a global attribute, so the view can find the data from your controller.
For example:
#like = ...
Then in your view you can add a local to be rendered:
$("#song_like").load("<%=j render partial: '/components/song_like', locals: {like: #like} %>");
But, you need to change your partial to be a partial. And change the variable to like so it will be rendered in the right way.
Hope it helps!
UPDATE
If you want to hit a specific song you can render it with each and then assign an id to your post's class
For example:
<% #posts.each do |post| %>
<div class="post-content">
... other stuff ...
<div class="likes like-post-<%= post.id %>">
.. number of likes
</div>
<%= link_to "Like", link_route_path(post) %>
</div>
<% end %>
# controller
# So you can use the id in your js view
#id = params[:id]
# view.js
$(".like-post-" + "<%= #id %>").html("<%= #s.thumbs_up_total %>");
Hope the idea helps.
change rendering like this:
<div class="col-3" id="song_like">
<%= render partial: '/components/song_like', locals: {s: #s, like: true} %>
</div>
then in partial:
<%= link_to like_song_path(s.id, like: like), method: :post, remote: true do %>
<i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <%= s.thumbs_up_total %>
<% end %>
and in controller of like_song
should define
#s= Song.find(params[:id])
like = Like.create(like: params[:like], user: current_user, song: #song)
#like = !like.like # opposite to your current status
rest of the things good and then in like.js.erb
$('#songs_like').html("<%= escape_javascript(render partial: '/components/song_like', locals: { s: #s, like: #like } ) %>")

Rails Dev environment with Javascript and Ajax

There's something I definitely don't understand going on in the background in dev.
I have an app which I've been developing locally on my Mac, and it has a form which makes an Ajax call "remote: true". It stopped working, no Ajax call, nothing in the logs.
The only way I could get it to start working again was to edit my _form.html.erb partial by adding a second input field (identical to the original, straight copy and paste). Refresh the page, then it worked. I've unedited my original edit, so the code is back to where it originally was (when it was not working), but now it's working.
What does the edit cause to happen? Is there someway I can cause it to happen without editing my code?
Thanks.
----- EDIT adding code -----
My form is (the text_field_tag is what I copied and pasted)
<div id="friend-lookup">
<h3>Search for friends</h3>
<%= form_tag search_friends_path, remote: true, method: :get, id: 'friend-lookup-form' do %>
<div class="form-group row no-padding text-center col-md-12">
<div class="col-md-10">
<%= text_field_tag :search_param, params[:search_param],
placeholder: "first name, last name or email", autofocus: true,
class: 'form-control search-box input-lg' %>
</div>
<div class="col-md-2">
<%= button_tag(type: :submit, class: "btn btn-lg btn-success") do %>
<i class="fa fa-search"></i> Look up a friend
<% end %>
</div>
</div> <!--- form-group -->
<% end %>
<%= render 'common/spinner' %>
<% if #users %>
<% if #users.size > 0 %>
<div id="friend-lookup-results" class="well results-block col-md-10">
<table class="search-results-table col-md-12">
<tbody>
<% #users.each do |user| %>
<tr>
<td><strong>Name:</strong> <%= user.full_name %></td>
<td><strong>Email:</strong> <%= user.email %></td>
<td><strong>Profile:</strong> <%= link_to "View Profile", user_path(user),
class: "btn btn-xs btn-success" %>
<% if current_user.not_friends_with?(user.id) %>
<%= link_to "Add as my friend", add_friend_path(user: current_user, friend: user),
class: "btn btn-xs btn-success", method: :post %>
<% else %>
<span class="label label-primary">
You are friends
</span>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% else %>
<p class="lead col-md-12">
No people match this search criteria
</p>
<% end %>
<% end %>
<div id="friend-lookup-errors"></div>
</div>
And the javascript is
# assets/javascript/friends.js
var init_friend_lookup;
init_friend_lookup = function() {
$('#friend-lookup-form').on('ajax:before', function(event, data, status){
$('#friend-lookup-results').replaceWith(' ');
show_spinner();
});
$('#friend-lookup-form').on('ajax:after', function(event, data, status){
hide_spinner();
});
$('#friend-lookup-form').on('ajax:success', function(event, data,status){
$('#friend-lookup').replaceWith(data);
init_friend_lookup();
});
$('#friend-lookup-form').on('ajax:error', function(event, xhr, status, error){
hide_spinner();
$('#friend-lookup-results').replaceWith(' ');
$('#friend-lookup-errors').replaceWith('Person was not found.');
});
}
$(document).ready(function() {
init_friend_lookup();
});
You may be used to installing JavaScript behavior in response to the window.onload, DOMContentLoaded, or jQuery ready events. With Turbolinks, these events will fire only in response to the initial page load—not after any subsequent page changes.
Change the "ready" event for 'turbolinks:load', and repeat the same step with you all events.
$(document).on('turbolinks:load', function () {
init_friend_lookup();
});
Read the documentation, https://github.com/turbolinks/turbolinks
Maybe this will help someone out there.
I am running Rails 5.
What was tricky was that it seemed intermittent.
My problem seems to be turbolinks related. Removing turbolinks, in javascript/application.js
//= require turbolinks
seems to have fixed the problem consistently.

Rails assign ids to elements in builder to access using jQuery

I'm using the Rails builder to build multiple :pay objects
<%= f.fields_for :pay do |builder| %>
<%= render "non_taxable_pays", :f => builder %>
<% end %>
This is rendering _taxable_pays multiple times as desired
_taxable_pays.html.erb
<div class="row">
<%= f.hidden_field :employee_id %>
<%= f.hidden_field :ee_pay_id %>
<%= f.hidden_field :pay_sub_head_id %>
<div class="col-md-5">
<div class="col-md-5">
<div class="form_indent1"><div class="form_indent1"><%= f.object.ee_pay.company_pay.description %></div></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-7">
<div class="form_indent1"><span>€ </span><%= f.text_field :rate, value: number_to_currency(f.object.rate), class: "currency_input" %></div>
<div class="form_spacer"></div>
</div>
</div>
<div class="col-md-7">
<div class="col-md-4">
<div class="form_indent1"><%= f.text_field :amount, value: number_to_currency(f.object.amount, :unit => ""), class: "number_input" %></div>
<div class="form_spacer"></div><br />
</div>
<div class="col-md-4">
<div class="form_indent1"><%= f.object.ee_pay.company_pay.units %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><span>€ </span><%= number_to_currency(f.object.rate*f.object.amount) %></div>
<div class="form_spacer"></div>
</div>
</div>
</div>
My issue is in the partial _taxable_pays above. In the last section I have code that displays the value * the rate f.object.rate*f.object.amount. This is great when the page is first displayed as it calculates it based on the values in the database.
I'm now looking to dynamically update this field using jQuery if the user changes the values in the text_fields holding the :rate or :amount. But for the life of me I can't figure out how I should assign id's to the different renders or access them using jQuery.
Can anyone point me in the right direction?
Thanks for looking
So this post helped me come up with my solution
Creating unique id for <fieldset> when using form_for Rails Nested Model Form
I put this at the top of the _taxable_pays partial
<% partial_type = "#{f.object.class}" %>
<% partial_id = "#{f.object.id}" %>
and I was then able to assign ids to the desired elements such as
<span id="<%= "#{partial_type}-value-#{partial_id}" %>
Might help someone in the future

Jquery mobile navbar not active after session log in (Rails)

1) This is my Login page:
<% provide(:title, 'Sign In') %>
<div data-role="page" data-url="/signin/">
<h1>Sign In</h1>
<%= form_for(:session, url: sessions_path) do |f| %>
<div>
<%= f.text_field :username_or_email, placeholder: "username or email", autofocus: true %>
</div>
<div>
<%= f.password_field :password, placeholder: "password" %>
</div>
<div>
<%= f.submit "Sign In", rel: "external" %>
</div>
<% end %>
</div>
2) This is my Home page after login:
<% provide(:title, #user.name) %>
<div data-role="page" id="home" data-url="/users/<%= #user.id %>/" >
<div data-role="header">
Menu
<h4>Home</h4>
<%= link_to 'New', new_pin_path, rel: "external" %>
</div>
<% if !#user.pins.any? %>
<h3>Welcome to Pins!... Enter your first pin.</h3>
<% end %>
<%= render #user.pins %>
</div>
<div data-role="page" id="menu">
<div class="ui-grid-a center">
<div class="ui-block-a menublock">
Home
</div>
<div class="ui-block-b menublock">
<%= link_to 'Friends Pins', pins_path %>
</div>
<div class="ui-block-a menublock">
<%= link_to 'Settings', edit_user_path(current_user) %>
</div>
<div class="ui-block-b menublock">
<%= link_to "Sign Out", signout_path, method: "delete" %>
</div>
</div>
</div>
So basically, after I log in and try clicking on Menu I get no response (unless I refresh the page).
3) This is how my session login works:
I was going to paste it but it's super long, I basically used the same thing that is going on here:
http://ruby.railstutorial.org/chapters/sign-in-sign-out#top
4) Trailing slashes (this is a requirement by jQuery Mobile): I thought my problem may be because I did not have trailing slashes set on all the urls, so I added this to my application.rb: config.action_controller.default_url_options = { :trailing_slash => true } And although it fixed a lot of the navigation between pages, it does not fix the issue after my session log in.
5) Also note that when I refresh the home page after login, the navbar does work correctly.
You are missing a "data-rel" tag. Try the following:
Menu

Javascript and Ruby Sidescrolling

So im working on a RoR app and would appreciate a bit of help with something. In this app, I've got a series of discussions, posted by users, with comments below, also posted by users. In terms of design, i thought it would be cool if each discussion would take up the entire screen with a button to the right of it. pressing this button would cause the view to move and reveal another discussion. Any suggestions about how I would go about doing this? heres the discussion partial I have currently. thanks!
<link href='http://fonts.googleapis.com/css?family=Titillium+Web:400,300' rel='stylesheet' type='text/css'>
<% content_for :script do %>
<%= javascript_include_tag 'hover_content' %>
<% end %>
<% #micropost = Micropost.new %>
<% #micropost.discussion_id = discussion.id %>
<li>
<div class = "intro-bar"><span class = "intro"><%=discussion.intro %></span></div>
<div class = "content-bar">
<span class = "content"><%= discussion.content %></span>
</div>
<input type='button' id='hideshow' value='hide/show'>
</li>
<span class = "timestamp">
Posted <%= time_ago_in_words(discussion.created_at) %> ago.
</span>
<% if signed_in? %>
<div class = "row">
<aside class = "span4">
<section>
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Post a comment" %>
</div>
<%= f.hidden_field :discussion_id%>
<%= f.submit "Break Up", class: "btn btn-large btn-breakup",:name => "break_up" %>
<%= f.submit "Stay Together", class: "btn btn-large btn-staytogether", :name => "stay_together" %>
<% end %>
</section>
</aside>
</div>
<% end %>
<div class = "comments">
<% discussion.microposts.each do |micropost| %>
<div class = 'comment-box'>
<li>
<div class = "comment-pic"></div>
<div class = "post-comment"><%= micropost.content%></div>
</li>
</div>
<% end %>
</div>
Your best bet would be a carousel.
For jQuery: http://sorgalla.com/projects/jcarousel/
(The "Special Examples" section has a text scroller which looks like what you want, but vertical)
For Prototype: http://code.google.com/p/prototype-carousel/

Categories