I got this menu on my website
%button.dropdown-button
.current-user{onclick:'showMenu()'}
%img.current-user-image{src:current_user.picture_url}
= current_user
%i.fa.fa-bars{'aria-hidden':true}
.dropdown-content
.menu-option{onclick:'showFilters()'}
Filter Transactions
%i.fa.fa-paper-plane{'aria-hidden':true}
.transaction-filters
.filter-option
My Transactions
%i.fa.fa-square-o
%a{href:'#'}
.menu-option
Balance History
%i.fa.fa-history{'aria-hidden':true}
%a{href:destroy_user_session_path}
.menu-option
Sign Out
%i.fa.fa-sign-out{'aria-hidden':true}
And I got this timeline with transactions
.timeline-container
- #transactions.each do |transaction|
.transaction-container
.transaction-header-container
.transaction-kudos-container
= "+#{transaction.amount}"
%span.currency
₭
.transaction-avatar-container
%div
= image_tag transaction.receiver_image, class:'avatar'
.transaction-body-container
.transaction-content
%span
= "#{transaction.sender.name}:"
%span.highlighted
= "+#{transaction.amount} ₭"
%span
to
%span.highlighted
= transaction.receiver_name_feed
%span
for
%span.highlighted
= transaction.activity_name_feed
%div
-#%button#like-button
-# Like
%span.post-time-stamp
= "#{distance_of_time_in_words(DateTime.now, transaction.created_at)} ago"
= paginate #transactions
They are both rendered on my index.html.haml
So when I click the div .filter-option.sent I want to change the code change from
- #transactions.each do |transaction|
to
- #all_transactions.each do |transaction|
to filter out the transactions of the current user without reloading the page.
These variables are defined in my controller
#transactions = Transaction.order('created_at desc').page(params[:page]).per(20)
#all_transactions = Transaction.all_for_user(current_user)
With in my model the method all_for_user
def self.all_for_user(user)
Transaction.where(sender: user).or(Transaction.where(receiver: user)).order('created_at desc').page.per(20)
end
I tried a lot of things with AJAX but nothing seems to please me. Somebody can help me?
So if you'd like to replace that #transactions list with AJAX you will need to do a few things..
1) Move the #transactions block into a partial that takes a local variable.
#transactions-wrapper
= render partial: 'transactions/list', locals: {transactions: #transactions}
2) Create a link that submits to a route, that hits a controller action as #js ('data-remote': true ) ( or write a javascript function that triggers $.ajax request: https://www.w3schools.com/jquery/ajax_ajax.asp
%a.transaction-filter{href: "/transactions/#{transaction_type}", 'data-remote': true}
or ex..
%a.study{href: "/transactions/recent", 'data-remote': true}
%a.study{href: "/transactions/past", 'data-remote': true}
3) define the route
get '/transactions/:type' => 'transactions#filter'
4) re-assign the variable based on the filter, and re-render that partial with the new data in a filter.js.erb file thats in the view directory -> app/views/transactions
def filter
#filtered_transactions = Transactions.where(type: params[:type] ).order('created_at DESC')
respond_to do |format|
format.html
format.js { render :action => 'filter.js.erb', :layout => false}
end
end
$("#transactions-wrapper").html("<%= j render(:partial => 'transactions/list'', :locals => { transactions: #filtered_transactions } ) %>");
alert('Transactions have been filtered, yo')
Let me know if that makes sense! Except please don't actually javascript alert at the end ;)
Related
I have an AJAX call in my application.js which sends 3 pieces of data to my events_controller#check action:
//application.js
$(document).on('click', "#check-button", function(){
...
$.ajax({
url: '/events/check',
data: {checkList: checkList , selected_date: selectedDate , length: length },
}
);
});
my check action:
#events_controller.rb
def check
checkList = params[:checkList]
selected_date = params[:selected_date]
length = params[:length]
busy_array = Array.new #this needs to be rendered in the view
...
busy_array.push(user.id) #busy_array is a list of user ids from database
end
#routes.rb
resources :events do
get :check, on: :collection
end
The view:
<button id="check-button" type="button">Check</button>
<div class = "col-md-6" id="unavailable">
<h2>Unavailable on this day:</h2>
<ol id="unavailable-list">
<li>THIS LIST SHOULD BE POPULATED BY BUSY_ARRAY</li>
</ol>
</div>
Now I need to send back data from events_controller#check to the view, but I don't know how to send busy_array to be rendered in events\new.html.erb
Thanks for you help, I am a ruby/JS beginner
busy_array = Array.new #this needs to be rendered in the view
If that has to be available in the view, you need to define an #instance variable:
def check
checkList = params[:checkList]
selected_date = params[:selected_date]
length = params[:length]
#busy_array = Array.new
...
#busy_array.push(user.id) #busy_array is a list of user ids from database
end
Each time you call a controller#action, the data/variables within the action are bound by local scope.
Outputting data in the view requires the variable to be made available across the entire instance of the class (not just the action/function). Thus #busy_array.
Fix
#app/views/events/....
<%= button_to "Check", events_check_path %>
<div class = "col-md-6" id="unavailable">
<h2>Unavailable on this day:</h2>
<ol id="unavailable-list"> </ol>
</div>
#app/assets/javascripts/application.js
$(document).on('click', "#check-button", function(e){
...
$.get('/events/check', {checkList: checkList , selected_date: selectedDate , length: length});
});
#app/controllers/events_controller.rb
class EventsController < ApplicationController
def check
#busy_array = User.joins(:event).where(event: { ... }).pluck(:id) #-> return user ids where event.x = y
respond_to do |format|
format.js #-> invokes app/views/events/check.js.erb
format.html #-> invoked when HTML request sent
end
end
end
#app/views/events/check.js.erb
<% #busy_array.each do |id| %>
$("ol#unavailable-list").append("<%=j id %>")
<% end %>
I don't know how to send busy_array to be rendered in events\new.html.erb
The variable will be available in new if it's an #instance var:
#app/views/events/new.html.erb
<%= #busy_array %>
The view is part of the instance of your EventsController class, but outside the scope of the check method. When you send a request to Rails, it uses an instance of the Controller to compile a set of HTML to return to your browser.
For example, you could sum up the EventsController flow as such:
Request > Routing > EventsController.new(request).action > Returned HTML
If you set EventsController.new(request) manually, you'd have the following:
#event = EventsController.new request
#event.check #-> "busy_array" locally scoped to this function
#event.response #-> outputs view code.... #busy_array needs to be instance var
You'll understand better if you read up about MVC:
For a real AJAX request in Ruby on Rails, you need to send response from check action in JS format.
events_controller.rb
def check
checkList = params[:checkList]
selected_date = params[:selected_date]
length = params[:length]
#events = Event.where("checklist = ? and date = ?, checkList, selected_date).limit(length.to_i)
...
respond_to do |format|
format.js
end
end
Now, in your view, instead a check.html.erb, you will have check.js.erb. In this Javascript file, you can access to your # variables and render partials or wherever.
check.js.erb
$("#unavailable-list").append('<%= escape_javascript( render :partial => "events/event", :collection => #events ) %>');
_event.html.erb
<li><%= event.name %></li>
I change busy_array for events array because I don't know what's exactly busy_array but you can change it.
This is the flow for an AJAX request.
I have trying to follow this question but I am stuck.
In my controller I have:
def index
if params[:sort] == 'stars'
#projects = [Project.first]
else
#projects = Project.all
end
respond_to do |format|
format.html
format.js { render 'populate_projects', :formats => [:js] }
end
end
in routes:
get '/inspire/:sort' => 'projects#index'
in view:
= collection_select :project, :id, Project.all, :id, :name, {}, {:onchange => '$.get("/inspire/stars")'}
%div#normal
= render 'projects_list'
%div#stars{ style: 'display: none' }
my _projects_list.html.haml has:
%div
- #projects.each do |project|
%div
%p
#more code...
and finally in populate_projects.js.haml:
:plain
$("#stars").html("#{escape_javascript render(partial: 'projects/projects_list')}");
$("#normal").hide();
$("#stars").show();
Probably the program doesn't make sense as I am testing if ajax call is working. However, what should happen is when I change the state of dropdown an ajax call must be made which renders 'propulate.js.haml' and list of projects must change from all to just first, but is not. In my terminal I can see that call is being made but 'populate.js.haml' is never rendered. Can someone please help!
Make sure your Ajax call requests the JS format:
= collection_select :project, :id, Project.all, :id, :name, {}, {:onchange => '$.get("/inspire/stars.js")'}
If you want to make an ajax call you need to include:
"data-remote" => true
See here for more information
I've got a flashcard system that allows users to create and go through sets of flashcards. I'm currently refactoring it to make it more efficient, but I'm running into a similar problem that I was before. Rendering the buttons through Javscript causes the buttons to not be clickable anymore unless the Javascript is reloaded. Instead of having 500 Javascript pages running in the background, I changed it so I didn't need it anymore. However, my paths are passing the parameters of the current card to the controller. Since I'm no longer generating the buttons via JS, however, the buttons are passing the parameter as the original card at page load.
<%= link_to ">", flashcard_path(type: "next", old: #card.id, status: #is_read), remote: true, class: "btn" %>
How can I update the #card.id without re-rendering the entire button? I'm open to suggestions if I need to change a bunch of stuff, too. I'm sure I m doing this in a strange way- as that is how I tend to do things. :)
This is the javascript that re-renders the flashcard and the accompanying controller method.
$('#id_number').html("<%= #card_num %>");
$('#flashcard-title').html("<%= escape_javascript(#card.title) %>");
$('#flashcard-lines').html("<%= escape_javascript(render partial: 'flashcard_lines', :locals => { card: #card, is_read: #read }) %>");
$('#flashcard-body').html("<%= escape_javascript(#card.body) %>");
def flashcard
all = FlashCard.all
old_flashcard = FlashCard.find(params[:old].to_i)
old_index = FlashCard.all.index(old_flashcard)
case params[:type]
when "new"
#card = FlashCard.new
#card.save
#read = false
when "edit"
#card = old_flashcard
#read = false
when "next"
if old_index == all.length - 1
back = 0
else
back = old_index + 1
end
binding.pry
#card = all[back]
#read = true
when "back"
if old_index == 0
back = all.length - 1
else
back = old_index - 1
end
#card = all[back]
#read = true
when "save"
old_flashcard.save
#card = old_flashcard
#read = true
when "delete"
old_flashcard.destroy
#card = FlashCard.all.last
else
#card = FlashCard.find(0)
#read = true
end
if params[:status]
#read = params[:status]
end
#card_num = FlashCard.all.index(#card) + 1
respond_to do |format|
format.html
format.js
end
end
I am not sure if I am understanding your problem correctly, but maybe you could do something like this?
$('#current_btn_id').attr('old',new_id);
I'm trying to follow along with the instructions on how to implement jquery-tokeninput here:
How to use jquery-Tokeninput and Acts-as-taggable-on
I am trying to attach tags to a "post". I can use the text field in my form to create new tags. However, the javascript just will not fire at all. It's as if none of the code even exists. I don't get any error messages. The text field just acts as a normal text field with no javascript events firing. What can be the issue? Here is my relevant code:
post model
attr_accessible :tag_list
acts_as_taggable_on :tags
posts controller
def tags
query = params[:q]
if query[-1,1] == " "
query = query.gsub(" ", "")
Tag.find_or_create_by_name(query)
end
#Do the search in memory for better performance
#tags = ActsAsTaggableOn::Tag.all
#tags = #tags.select { |v| v.name =~ /#{query}/i }
respond_to do |format|
format.json{ render :json => #tags.map(&:attributes) }
end
end
routes
# It has to find the tags.json or in my case /products/tags.json
get "posts/tags" => "posts#tags", :as => :tags
application.js
$(function() {
$("#post_tags").tokenInput("/posts/tags.json", {
prePopulate: $("#post_tags").data("pre"),
preventDuplicates: true,
noResultsText: "No results, needs to be created.",
animateDropdown: false
});
});
Out of frustration I also created a posts.js.coffee file just to see if that was the problem:
$ ->
$("#post_tags").tokenInput "/posts/tags.json",
prePopulate: $("#post_tags").data("pre")
preventDuplicates: true
noResultsText: "No results, needs to be created."
animateDropdown: false
post form view
<%= f.label :tag_list %>
<%= f.text_field :tag_list, :id => "post_tags", "data-pre" => #post.tags.map(&:attributes).to_json %>
Am I missing something here? Any help would be greatly appreciated!!!
Thanks!!
I'm using the jQuery autocomplete plugin, and I want to customize this event:
select: function(event, ui) {
$('.topic_field').val(ui.item.topic.name);
return false;
Essentially, it triggers callbacks when an element from the dropdown list is selected. As of now, it only adds the selected element to the text field. I want both the field to be populated and for my application to send a POST request to the video update controller action, so that the user does not need to explicitly press the button. How can I do this?
UPDATE:
Here is the form in the show view of the video controller:
<%= form_for #video, :url => {:action => "update"}, :remote => true do |f| %>
<div class="field">
<%= f.text_field :topic_names, :class => "topic_field" %>
</div>
<%= f.submit "Add Topic" %>
<% end %>
Here is my jQuery code:
var url = $('.edit_video').attr('action');
var val = ui.item.topic.name;
$.post(url, {data:val});
This is in my routes.rb:
resources :videos
resources :video_votes
resources :users
resources :profiles
resources :genres
resources :topics
resources :topicables
resource :session
Here's my update action:
def update
#video = current_user.videos.find(params[:id])
respond_to do |format|
if #video.update_attributes(params[:video])
format.html { redirect_to(#video) }
format.js
else
format.html { render :action => "edit" }
end
end
end
Check out the jQuery.post documentation on how to post the data from your select box to the relevant controller action.
I'm not familiar with the autocomplete plugin, but I presume it follows an onChange event on your select box. When the user has made a selection, you should execute the following (untested):
var url = $('myForm').attr('action');
var val = $('mySelectBox').val();
$.post(url, {data:val})
In your controller, you could access this using:
params[:data]
which would return the value of your select box. You can then use this as normal in your controller code.
use the jquery ajax function to fetch the data from your action url ("/topics/list") or something
$.post('video/update',
data: {yourdata},
function(data) {
//callback function
}
);
in your video#update be sure to return something for your js request:
def update
blah
respond_to do |format|
format.js { return somethinghere }
end
end