In react, I could easily re-render a view by passing results from controller. I wish not to use React at this stage and was wondering if it's possible with JQuery?
I have few objects on page, and when clicked, I should see its content. Click the other object, I see its content etc. Sense? I was inspired by this dribbble.
I may not be doing this the right way but this is what I have:
Controller:
def index
selected_contract = params[:selected_contract] || current_user.contracts.last.id
#contracts = current_user.contracts.order(created_at: :desc).all
#selected_contract = current_user.contracts.find_by(id: selected_contract)
end
View:
<% #contracts.each do |contract| %>
<button class="ui button test" id="<%=contract.id%>"><%=contract.name%></button>
<% end %>
......................................
When clicked, show its content
....................................
<%= #selected_contract.name %>
JS:
$( ".ui.button.test" ).click(function(e) {
let { id } = this
console.log(id)
$.ajax({
url: `/url/${id}`,
type: 'POST',
success: function(result) {
//$('#listview').redraw()
console.log('success')
}
});
});
Routes are set properly so I get the params in the controller just fine. Is there a re-render a view, just like rerender a prop in React for jquery? Am I doing this the correct way?
If you are using jquery listview this should work.
$( "#listview" ).listview( "refresh" );
Reference
https://api.jquerymobile.com/listview/#method-refresh
or since its rails you can reload or render the partial view in your server side as well.
Related
I've lost in thought. I have a checkbox that I want to use to transfer a corresponding object to another scope on my page. Moreover, I want only to transfer one field of this checked object. I had used earlier Ajax by creating a .json file and then I responded to it in my controller. In my case input checkbox doesn't seem to have a remote: true option.
views/tasks/_index.html
<h3>Tasks database</h3>
<table>
<% #tasks.each do |task| %>
<tr class='tasks' id="task_<%= task.id %>">
#Some stuff
<td>
<input type="checkbox" class='check' data-id="<%= task.id %>" >
</td>
</tr>
<% end %>
</table>
<h3>Completed</h3>
<div class="complete-tasks">
</div>
Hence, I'm trying to accomplish that using an event via javascript.
So far I've managed to write some javascript code that moving my entire object.
application.js
$(document).on('ready page:load', function () {
$('.check').on('change', function(){
if ($(this).is(':checked')) {
id = $(this).attr('data-id');
task = $(this).closest("tr");
$('.complete-tasks').last().after(task);
}
});
})
But I want to relocate only one 'title' field using Ajax. Can someone please explain me how to accomplish that? I suspect I need to pass in some id's in checkbox and to define $.ajax.
models/task.rb
class Task < ActiveRecord::Base
scope :complete, -> { where(complete: true) }
scope :incomplete, -> { where(complete: nil) }
belongs_to :user
end
All you have to do is make the request to the url and then move the table row/title cell.
$(document).on('ready page:load', function () {
$('.check').on('change', function(){
if ($(this).is(':checked')) {
id = $(this).attr('data-id');
//Url is the site you want to hit.
var jqXHR = $.ajax(url);
var element = this;
jqXHR.done(function(data){
//Ajax finish here.
task = $(element).closest("tr");
$('.complete-tasks').last().after(task);
});
}
});
});
Edit: Fixed context use.
Check the jQuery documentation on how to set up the jqXHR properly:
http://api.jquery.com/jquery.ajax/
I appreciate that there may be many answers out there but if there are i cant quite interpret them to suit my needs..I am looking to update a records attribute in my model using ajax.
In my case the attribute selected: true
In my scenario i am clicking on an element and looking to update that elements record in the model
<ul class="components">
<% #component.each do |c| %>
<li id="<%= c.component_name %>" data-id="<%= c.id %>" data-remote="true"><%= c.component_name %></li>
<% end %>
</ul>
jQuery
$('#Literacy, #Numeracy').on('click', function(){
var component_name = $(this).text();
var component_id = $(this).data('id');
data_send = { id: component_id }
$.ajax({
method: 'put',
url: '/components/selected_component',
data: data_send,
success: function(data) {
console.log(data)
}
});
});
Controller
def selected_component
#component = Component.find(params[:id])
#component.update_attributes(selected: true)
end
Maybe im looking at this incorrectly but how can i get the id via the click event (stored as component_id) into my selected_component method
Im missing a few bits here but struggling with what today
At the moment I am getting an error
Missing template components/selected_component
but i dont want to render that page after successful update, I just want to stay on the same page
EDIT
to solve my issue i just had to add this to my format.js
{ render nothing: true }
A missing template error corresponds to not having a view that knows what to do when it gets a JavaScript request.
In your views/components/, just make an selected_components.js.erb file and that should clear the error you're getting.
I'm trying to implement an ajax voting system for a model "Things", where if a user votes on Thing then a new Thing appears in the old one's place, which he can then vote on, and so on. This takes place on the Thing view itself.
I'm pretty sure this exact code was working a week ago, but now it mysteriously broke. Now, the Thing is replaced upon the first vote, but after that, voting no longer brings forth a new Thing:
views/things/show.html.erb
<div id="randajax">
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), upvoterandom_thing_path(#rand.id), remote: true, method: :get %>
<script type="text/javascript">
function reload_script() {
$(".rand_up_vote").click(function () {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
$('#randajax').html(data);
reload_script();
});
});
}
reload_script();
</script>
</div>
controllers/things_controller.rb
def upvoterandom
#thing = Thing.find(params[:id])
UpVote.create!
#rand = Thing.all.first
render text: "<a data-method=\'get\' data-remote=\'true\' href=\'" + upvoterandom_thing_path(#rand.id) + "\'><img alt=\'Upvote\' class=\'rand_upp_vote\' src=\'/assets/UpArrowGray.jpg\' /></a>".html_safe
end
Apparently the issue is that an item created with ajax can't execute javascript. The web console shows that the upvoterandom_thing_path is getting executed, but nothing happens to the randajax div. I tried giving the Thing created from the original javascript a differenc class with different javascript and that didn't work either, although a seperate item ("THIS_WORKS") with the same class executed the same javascript normally:
views/things/show.html.erb
<%= link_to "THIS_WORKS", "#", class: "TEST_TEST", remote: true %>
<div id="randajax">
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), upvoterandom_thing_path(#rand.id), remote: true, method: :get %>
<script type="text/javascript">
function reload_script() {
$(".rand_up_vote").click(function () {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
$('#randajax').html(data);
reload_script();
});
});
}
reload_script();
</script>
<script type="text/javascript">
$(".TEST_TEST").click(function () {
$('#randajax').html("TEST");
});
</script>
</div>
controllers/things_controller.rb
def upvoterandom
#thing = Thing.find(params[:id])
UpVote.create!
#rand = Thing.all.first
render text: "<a data-method=\'get\' data-remote=\'true\' href=\'" + upvoterandom_thing_path(#rand.id) + "\'><img alt=\'Upvote\' class=\'rand_up_vote\' src=\'/assets/UpArrowGray.jpg\' /></a>".html_safe
end
Can anyone explain why this is happening or how I can fix this?
When you set it up, you do this in your javascript:
$(".rand_up_vote").click(function () {
...
This sets up the click event on the elements. When one of the elements is replaced, or a new one is added, it hasn't had this event added to it, so it won't work like the others.
To fix this, you need to add this same event to the new element, OR remove the event from all elements and then add it to all elements (if you don't remove it first you risk firing the same event twice on a click or whatever).
EDIT with a proposed solution.
The simplest way is to add an onclick attribute to your elements, to run the reload_script() function. Change this so that it doesn't add an onclick to the events. I was about to start editing your code and i noticed that the reload_script function calls itself at the end of the anonymous function you're adding as the onclick event: this means that when you click on a .rand_up_vote element, it will do the AJAX get, replace the html, and then add another onclick to all the elements. This is definitely not right - was this an earlier attempt to fix this problem?
You probably just need something like this:
<div id="randajax">
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), upvoterandom_thing_path(#rand.id), remote: true, method: :get %>
<script type="text/javascript">
function reload_script() {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
$('#randajax').html(data);
});
}
</script>
</div>
now edit the html so that each .rand_up_vote element has an onclick="reload_script()" attribute.
I have a profile page where I render all of the user's lists using a partial:
users/show.html.erb
<%= render #lists %>
For each list I show how many wishes are associated:
lists/_list.html.erb
<p class="muted" id="wishes_count"><%= pluralize(list.wishes.count, "wish") %></p>
I'm using drag and drop to allow the user to move wishes from one list to another using jQuery sortable.
Right now, I'm using the following code:
wishes.js.erb
$(document).ready(function(){
$('.user_list_wishes').sortable({
connectWith: ".user_list_wishes",
items: ".user_list_wish",
placeholder: "sortable_placeholder",
update: function(e, ui)
{
if (this === ui.item.parent()[0])
{
item_id = ui.item.data('item-id');
list_id = $(this).data('list-id');
position = ui.item.index();
$.ajax({
type: 'POST',
url: $(this).data('update-url'),
dataType: 'json',
data: { id: item_id, wish: { row_order_position: position, list_id: list_id } }
}),
$("#wishes_count").html('<%= pluralize(list.wishes.count, "wish") %>')
}
}
})
})
This line of code:
$("#wishes_count").html('<%= pluralize(list.wishes.count, "wish") %>')
makes my application throw a NoMethodError undefined method 'wishes' for nil:NilClass
I believe it has something to do with how I render lists and reference them individually in my javascript?
Any suggestions on how to solve this problem is much appreciated!
You must handle the scenario where list is null using the following condition:
$("#wishes_count").html('<%= pluralize(list ? list.wishes.count : 0, "wish") %>')
I think the problem could be in your render call - according to the documentation:
If you have an instance of a model to render into a partial, you can use a shorthand syntax:
<%= render #customer %>
Assuming that the #customer instance variable contains an instance of the Customer model, this will use _customer.html.erb to render it and will pass the local variable customer into the partial which will refer to the #customer instance variable in the parent view.
So check that this is the case - do you have a partial called _lists.html.erb and a parent variable called list?
In one of my forms, I have an element called event_id which value I select from a dropdown box. Once I select event_id, I want to use Ajax to call the controller, and return panel_event_id as a ruby variable that I can use in the rest of the form. Here's what I'm doing:
In routes.rb, I have the following:
match 'panel_event_id', :to => "panels#event_id"
I have the following javascript function (not sure about the syntax):
<script type="text/javascript">
$('select').change(set_session_event_id);
function set_session_event_id()
{
var event_id = document.getElementById("event_id");
var event_id_value = event_id.value;
$.post('panel_event_id', { set_event_id: event_id_value });
}
</script>
What do I put in my panel_controler.rb, in the following method:
def panel_event_id
end
and how do I act on it back in my view?
You could render a json in your controller :
def panel_event_id
...
render :json => panel_event.as_json(:only => [ :id ])
end
After that, you could handle the success event of the post method. See the doc here : http://guides.rubyonrails.org/layouts_and_rendering.html and here http://api.jquery.com/jQuery.post/ and here http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json.