Passing the ID of a DOM element to rails controller - javascript

My model has Chords, which have a many-to-many relationship with Notes through Chordnotes. My chords/show looks like this:
<% #chord.notes.each do |note| %>
<li id="NoteID<%= note.id %>" >
<span class="content"><%= note.name %> (<%= note.description %>) (ID: <%= note.id %>)</span>
<span class="timestamp">
Created <%= time_ago_in_words(note.created_at) %> ago.
</span>
<span class="content">
<%= link_to "remove (not working)", '#' %>
</span>
</li>
<% end %>
I want the link_to tag to remove, not the note, but the Chordnote that links the Note to the Chord. I was trying to do this by referencing the #id in the < li > tag, which is the ID of the Note, and passing the Note ID and the Chord ID from the /show page the user was on. My Chordnote controller looks like this:
def destroy
#chord = Chord.find(chord-id) <-- how do I get this chord id??
#note = Note.find(note-id) <-- how do I get this note id??
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id).destroy
redirect_to chord_path(#chord)
end
This destroy action works when I hardcode chord-id and note-id with ID #'s, but I can't figure out how to pass the relevant Note and Chord IDs from the chords/show page.
Any help would be appreciated, thanks!

this is untested, mind you. But have you tried passing the relevant data through the link_to?
<% #chord.notes.each do |note| %>
<li id="NoteID<%= note.id %>" >
<span class="content"><%= note.name %> (<%= note.description %>) (ID: <%= note.id %>)</span>
<span class="timestamp">
Created <%= time_ago_in_words(note.created_at) %> ago.
</span>
<span class="content">
<%= link_to "remove (not working)", {controller: "whatever_controller", action: "destroy", chord_id: #chord.id, note_id: note.id } %>
</span>
</li>
<% end %>
and then you would access these in the destroy method like so
def destroy
#chord = Chord.find( params[:chord_id] )
#note = Note.find( params[:note_id] ) <-- how do I get this note id??
Chordnote.find_by(note_id: #note.id, chord_id: #chord.id).destroy
redirect_to chord_path(#chord)
end

Related

Rails 4 x AJAX: partial not reloading on click with remote: true

In my Rails 4 app, I have a Post model with a custom approval attribute.
I am trying to update this custom approval attribute from the Posts#Show page when the user clicks on one of three particular links set with remote: true.
The goal is to reload only the partial displaying the content of this attribute, and not the entire page.
Here is my Post show.html.erb view:
<div id="post_show_approval">
<%= render 'approval' %>
</div>
And here is my _approval.html.erb partial, located in the app/views/posts folder:
<ul>
<li>
<% if #post.approval == "ok" %>
<span class="ok_green">
<span class="glyphicon glyphicon-ok"></span>
Post Approved
</span>
<% else %>
<span class="approval_blue" %>
<%= link_to post_path(:id => #post.id, "post[approval]" => "ok"), :class => "post_appoval_link", remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-ok"></span>
Approve this post
</span>
<% end %>
<% end %>
</li>
<li id="post_show_require_edits">
<% if #post.approval == "edit" %>
<span class="edit_yellow">
<span class="glyphicon glyphicon-repeat"></span>
This post requires edits
</span>
<% else %>
<span class="approval_blue" %>
<%= link_to post_path(:id => #post.id, "post[approval]" => "edit"), :class => "post_appoval_link", remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-repeat"></span>
Require edits for this post
</span>
<% end %>
<% end %>
</li>
<li id="post_show_to_be_deleted">
<% if #post.approval == "remove" %>
<span class="remove_red">
<span class="glyphicon glyphicon-remove"></span>
This post needs to be deleted
</span>
<% else %>
<span class="approval_blue" %>
<%= link_to post_path(:id => #post.id, "post[approval]" => "remove"), :class => "post_appoval_link", remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-remove"></span>
Mark this post as to be deleted
<% end %>
</span>
<% end %>
</li>
</ul>
As you can see, all the links with the post_approval_link class are set with remote: true.
Then, I have updated my PostsController as follows:
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to post_path(#post) }
format.json { render :show, status: :ok, location: #post }
format.js
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
And I have created an update.js.erb file in the app/views/posts folder:
$('#post_show_approval').reload(true);
—————
UPDATE: as alternatives to the above line, I also tried
$('#post_show_approval').hide().show();
and
$('#post_show_approval').toggle().toggle();
But none of these seem to work.
—————
UPDATE 2: here is another thing I tried:
$('#post_show_approval').load('<%= j render "approval" %>');
But it is not working either.
—————
UPDATE 3: when I try only
$('#post_show_approval').hide();
or
$('#post_show_approval').toggle();
The div does disappear.
But I still did not find a way to make it reappear with its content updated.
—————
UPDATE 4: also, when I use:
$('#post_show_approval').append('<%= j render(partial: "approval") %>');
The approval partial does load with its updated content... the initial content does not disappear, so every time we click on one of the links, a new line of content stacks up.
—————
However, when I click on one of the three links with the post_approval_link class, the appoval attribute of the post is actually updated to the correct value, but the #post_show_approval div is not reloaded and I need to refresh the page to see the actual changes.
What am I missing in the implementation of this AJAX feature?
The problem was that I was not using the right JavaScript method.
With:
$('#post_show_approval').html('<%= j render(partial: "approval") %>');
It is now working like a charm.

Rendering a partial to an edit form inside a popover in rails 4

Hi guys I really need help here.
I'm making a todo app and displaying each task through an iteration. Next to each task I have a pencil glyphicon.
When I click on it, I want there to be a popover containing an edit form and edit the task on the spot. I'm having a ton of troubling rendering that form.
***** UPDATE *****
Clark helped me get the popover to work. But The form inside the popover is acting like a link instead of a form so I can't type in the text area.
This is my index.html.erb
<div id='user_tasks'>
<% #tasks.each do |task| %>
<ul>
<li>
<%= task.description %>
<%= link_to edit_task_path(task), :rel => 'popover', method: 'get', remote: 'true' do %>
<span class = 'edit_task_<%=task.id%> glyphicon glyphicon-pencil'> </span>
<% end %>
</li>
</ul>
<% end %>
</div>
This is the edit.js.erb
$(function(){
$('.edit_task_<%=#task.id%>').popover({
html: true,
title: 'edit',
content: <%= escape_javascript render 'edit_form', task:#task %>
}).popover('show'); });
and my controllers look like this:
def index
#new_task= Task.new
#tasks= Task.all
end
def create
#new_task= Task.new(task_params)
#task.save
redirect_to :back
end
def edit
#task= Task.find(params[:id])
end
_edit_form.html.erb looks like this: This isn't the edit form that I plan to use. Its just a copy of the create task form. I plan to fix it once I get the popover working.
<%= form_for task, :html=>{:class=> 'form-inline'} do |f| %>
<div class='form-group'>
<%= f.text_field :description, placeholder: 'create a task' %>
<%= button_tag(type:'submit', class:"btn btn-default btn-xs") do %>
<span class='glyphicon glyphicon-plus'></span>
<% end %>
</div>
<% end %>

Rails showing series of objects with form_for and Ajax

I'm trying to show a list of "Interests" that users can "follow" by clicking on a button associated with the Interest's image. Upon clicking the button to follow an Interest, the Interest (and it's corresponding image) should disappear from the list.
I'm using a hide function in a create.js.erb file called upon by a Relationship controller when the follow button is clicked, but the function will only hide the first Interest in the series of Interests--NOT the Interest the user clicked on that needs to disappear. So there has to be a better way to set this up, but I cannot, for the life of me, figure it out. Here's my current setup:
My Controller
class StaticPagesController < ApplicationController
def home
#user = current_user
#city = request.location.city
#interests = Interest.all
end
The home page
<%= render #interests %>
The partial
<div id="follow_form">
<div class="four columns portfolio-item interests">
<div class="our-work">
<a class="img-overlay">
<%= image_tag interest.image_path %>
<div class="img-overlay-div">
<h4><%= interest.name %></h4>
</br>
<h5>Placeholder
</br>
<%= interest.desc %></h5>
<%= form_for(current_user.relationships.build(followed_id:
interest.id), remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "I'm interested", class: "b-black" %>
<% end %>
</div>
</a>
<h3><%= interest.name %><span>features info</span></h3>
</div>
</div>
</div>
And the create.js.erb that's called upon by a Relationships controller when you click the button:
$("#follow_form").hide();
UPDATE
Here is the Relationships controller for additional clarification
def create
#interest = Interest.find(params[:relationship][:followed_id])
current_user.follow!(#interest)
respond_to do |format|
format.html { redirect_to(root_url) }
format.js
end
end
You need to provide something to differentiate the different "follow_forms" that you have on the same page. Otherwise, jQuery will just select the first element and only remove that one.
One idea of how to do this would be to append the "interest.id" to the end of the follow_form id
Update your partial to be like this (assuming your partial is called and located in /app/views/interests/_follow_form.html.erb:
<div id="follow_form<%="#{interest.id} %>">
<div class="four columns portfolio-item interests">
<div class="our-work">
<a class="img-overlay">
<%= image_tag interest.image_path %>
<div class="img-overlay-div">
<h4><%= interest.name %></h4>
</br>
<h5>Placeholder
</br>
<%= interest.desc %></h5>
<%= form_for(current_user.relationships.build(followed_id:
interest.id), remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "I'm interested", class: "b-black" %>
<% end %>
</div>
</a>
<h3><%= interest.name %><span>features info</span></h3>
</div>
</div>
</div>
This way each follow_form will have a unique ID attached to it. Then you can loop through your interests and call a partial on each one like this:
home page:
<% #interests.each do |interest| %>
<%= render 'interests/follow_form', :interest => interest %>
<% end %>
create.js.erb
$("#follow_form_<%= "#{#interest.id}" %>").hide())
Your controller action can stay the same.

How to create a rails form with checkboxes which uses GET?

The intended URL is
"versions/compare/id1/id2"
Obviously, this doesn't work, but shows the intention
<%= form_tag("/versions/compare/", :method => "get") do %>
<% versions.each do |v| %>
<% v.id == #version.id ? current_class = " current" : "" %>
<li class="version-list <%= current_class %>">
<%= check_box_tag(:compare_version, v.id) %>
<%= link_to v.user.name, version_path(v) %>,
</li>
<% end %>
<%= submit_tag("Compare") %>
<% end #form tag
%>
The code above produces http://localhost:3000/versions/compare/?utf8=%E2%9C%93&compare_version=13&compare_version=12&commit=Compare
Is there a way to modify the form (+ JS?) so that it gets the desired URL?
"versions/compare/id1/id2"
you need to understand how form_tag work, it can not change the url after rendering the document.
If you want to change the url, use jquery to change it.
Or, just submit the form into some other url like
<%= form_tag("/comparing_version")
and then, in the controller, after processing everything, you redirect user to
"versions/compare/id1/id2"

Is it possible to populate a javascript attribute from a records field?

I have a table of venue records which are being displayed on the index page as partials. Is it possible for the .left and .top values in the javascript to be populated by an integer field taken from venue records?
Also, how can I have the script shown run for each partial as it currently only applies to the first partial generated.
Venue partial:
<%= link_to venue do %>
<div class="venue_partial">
<div class="venue_icon">
<%= image_tag venue.venuetype.photo.url(:thumb), :class => 'image' %>
</div>
<span class="venue_partial_name"><%= venue.name %></span>
<span class="venue_area_and_type"><%= venue.venuetype.name %></span>
<span class="venue_area_and_type"><%= venue.area.name %></span>
</div>
<div id="venue_map_icon" style="position:absolute;"></div>
<script>
document.getElementById("venue_map_icon").style.left= "300px";
document.getElementById("venue_map_icon").style.top= "310px";
</script>
<% end %>
Thanks very much for any help its much appreciated!
Yes on both counts. The problem you have now is that you are referencing an element by an ID in javascript, but that ID is not unique, so javascript finds the first instance of this ID and applies the rules to it, not to the rest of your divs. To fix this, you need to use unique ids:
<%= link_to venue do %>
<div class="venue_partial">
<div class="venue_icon">
<%= image_tag venue.venuetype.photo.url(:thumb), :class => 'image' %>
</div>
<span class="venue_partial_name"><%= venue.name %></span>
<span class="venue_area_and_type"><%= venue.venuetype.name %></span>
<span class="venue_area_and_type"><%= venue.area.name %></span>
</div>
<div id="venue_map_icon_<%= venue.id %>" style="position:absolute;"></div>
<script>
document.getElementById("venue_map_icon_<%= venue.id %>").style.left= "<%= venue.left %>px";
document.getElementById("venue_map_icon_<%= venue.id %>").style.top= "<%= venue.top %>px";
</script>
<% end %>
Sure, it just needs to be output just like you do in the HTML:
document.getElementById("venue_map_icon").style.left = "<%= venue.somevalue %>px";

Categories