ajax controlling in rails - javascript

Hey guys I need to know the answers to some questions. First of all how do I handle ajax call when I am not returning anything from the controller because it always ask me for the view for the called function but since I have called that function using ajax how can it have a view.(I am using it in ROR(ruby on rails))
bookmark.html.erb
<div class="row">
<div id="page-wrapper-lbms" class="small-12 medium-12 large-12 columns dashboard-page">
<input type="hidden" id="bookmarked_against_req_id" value=<%= #data2%> />
<%
if #requests != nil
#requests.each.with_index do |request,index|
if request != nil
%>
<header>
<div style="text-align:center">
</span>
</div>
<h2 style="text-align:center"><%= request.title %></h2>
<div style="text-align:center">
<h6 style="color:#aaaaaa"><strong><%= request.is_service%></strong></h6>
</div>
</header>
<div class ="row">
<div class="small-12 medium-12 large-8 columns">
<div id="request-content-lbms" class="panel">
<p>
<%= request.description%>
</p>
</div>
<div id="list-request-cat-lbms">
<span class="fa fa-tag"></span>
<% if #tag[index] != nil
#tag[index].each do |cat| %>
<%= cat.title %>
<%end%>
<%end%>
</div>
</div>
<aside class="small-12 medium-12 large-4 columns" style="padding-left:10%">
<h3 ><strong>Syed Muhammad Ali Gardezi</strong></h3>
<time><%= request.created_at %></time><br />
<%end%>
<button class="button tiny">Schedule Meeting</button>
</aside>
</div>
</div>
<%end%>
<%end%>
<script>
function ajax_bookmark(abc , cde){
var cde = $('#bookmarked_against_req_id').val();
$.ajax({
type: "GET",
url: 'bookmark_request',
data: {
d:abc,
d1:cde
},
error:function(){
},
dataType: 'json',
//beforeSend:function(){},
//complete:function(o,s){},
success:function(data){
location.href ="/requests/bookmark"
},
type: 'get'
});
}
</script
bookmark_request
def bookmark_request()
data = params[:d]
data1 = params[:d1]
data2 = data1#["$oid"]#.split('"' , 6)
#asd
request_bookmarked = Request.getRequest(data)
bookmarked_against_Request = Request.getRequest(data2)
request_bookmarked_2 = request_bookmarked
bookmarked_against_Request_2 = bookmarked_against_Request
#asd
if bookmarked_against_Request_2[:favourites]
bookmarked_against_Request_2[:favourites] << request_bookmarked[:id]
else
bookmarked_against_Request_2[:favourites] = Array.new
bookmarked_against_Request[:favourites] = Array.new
bookmarked_against_Request_2[:favourites] << request_bookmarked[:id]
end
if request_bookmarked_2[:favourites_of]
request_bookmarked_2[:favourites_of] << bookmarked_against_Request[:id]
else
request_bookmarked_2[:favourites_of] = Array.new
request_bookmarked[:favourites_of] = Array.new
request_bookmarked_2[:favourites_of] << bookmarked_against_Request[:id]
end
request_bookmarked.update(Hash['favourites' ,request_bookmarked_2[:favourites]])
bookmarked_against_Request.update(Hash['favourites' ,bookmarked_against_Request_2[:favourites]])
#asd
bookmarks = Bookmark.where(request_id: bookmarked_against_Request[:id]).first()
#asd
b = bookmarks
if bookmarks != nil
#bookmarks.each { |bookmark| bookmark.update_attributes(corsponding_requests: request_bookmarked[:id]) }
b[:corsponding_requests] << request_bookmarked[:id]
b.update(Hash['corsponding_requests' , b[:corsponding_requests]] )
else
bookmark = Hash.new
bookmark["owner_req"] = session[:user]
bookmark["request_id"] = bookmarked_against_Request[:id]
bookmark["corsponding_requests"] = Array.new
bookmark["corsponding_requests"] << request_bookmarked[:_id]
Bookmark.createBookmark(bookmark)
end
flash[:notice] = "Request has been bookmarked successfully."
end
Now when ever I run this function i need it to go into the success function of ajax in bookmark.html.erb but the problem is it says I can't find the view. What is it that I am doinf wrong over here
Second when ever I need to return something I have read that I need to make a html helper but I can't figure out what a html helper is. and how can I return a string back to ajax function
Any help will be appreciated (I am new to AJAX)

You'll probably want to take a look at the rails guides - they're a great source of general grounding: http://guides.rubyonrails.org. For returning different responses based on the request format (ajax vs. html), see http://guides.rubyonrails.org/action_controller_overview.html#rendering-xml-and-json-data and #davidwessman's answer above.
Generally, you'll typically return JSON data from an ajax request; so, for instance, in the controller you might say
respond_to do |format|
format.js {render json: #my_ojects.to_json}
end
Note that there are several ways to render json, including the gems like rabl. If you're returning json like that, you don't need to render a rails view (unless you're using a view to build your json, like rabl does or is hinted at in davidwessman's answer with js.erb).
Hope that helps.

Gonna try to answer you :
First:
If you have a special action for your ajax call you only need:
def custom_action
end
This will render the custom_action.js.erb if called with ajax, for example a form with remote: true.
If you call one of your CRUD-actions and need to be able to respond to multiple formats:
def show
#book = Book.find(params[:id])
respond_to do |format|
format.html # will render show.html.erb
format.js # will render show.js.erb
end
end
If you put a link in your view:
link_to('Remote Ajax Call', book_path(#book), remote: true)
This link will call the method show and render as :js.
It will look for app/views/books/show.js.erb which may look something like:
<% if #book.present? %>
$('#book-title').html("<%=#book.title%>");
<%end%>
And in your view, close to the link above, this will then change the text inside a html-tag with I'd book-title.
<div id="book-title">
</div>
Second:
I do not understand what you mean by
...need to return something...
Can you add an example?
Hope that this can help you a bit.
Edit:
This is my try to understand what you want to do:
In your view:
<%= hidden_field_tag :bookmarked_against_req_id, value: #data2 %>
<% if #requests != nil %>
<% #requests.each.with_index do |request,index| %>
<% if request.present? %>
<%= link_to 'Bookmark it', bookmark_request_path(request), remote: true %>
<%= request.title %>
<%= request.is_service%>
<%= request.description%>
<% if #tag[index].present? %>
<% #tag[index].each do |cat| %>
<%= cat.title %>
<%end%>
<%end%>
<%= request.created_at %>
<%end%>
<%end%>
<%end%>
In your controller:
def bookmark_request()
request_bookmarked = Request.getRequest(params[:id]) # the params[:id] should be set in the request.
bookmarked_agains_Request = Request.getRequest(params[:bookmarked_against_req_id) # This is defined in your hidden_field_tag
When your action bookmark_requestis done. If the request was AJAX you will render the JavaScript-file bookmark_request.js.erb
Here you should have the script you put in your view:
If the resource is saved, you should put JavaScript to render 'Success' or if it failed you should do otherwise.
The flash[:notice] = "Request has been bookmarked successfully."will not be understood by your AJAX-request.

Related

incompatible encoding issue with escaping javascript helper

I'm working on a RSS reader and I have to check every x time if a new article is arrived. So I create a function for that in javascript who goes to a controller, then a service, back controller and finish with a js.erb view.
My first issue is that I have an encoding problem on the js.erb file.
My second issue is that even when I don't have data I can't stop the function before goes to the view file. The js.erb then I got a error because the data is nil.
My javascript function :
var actu = setInterval(myTimer, 20000);
function myTimer() {
$.ajax({
url: '/fluxes/actu',
method: 'GET',
});
}
My controller action:
def actu
#fluxes = Flux.all
#new_hash_article = Actualisation.new(#fluxes).call
if #new_hash_article.length >= 1
#new_hash_article.each do |key, value|
#flux = key
#article = value
respond_to do |format|
format.js
end
end
end
end
My service:
require 'rubygems'
require 'simple-rss'
require 'open-uri'
class Actualisation
def initialize(fluxes)
#fluxes = fluxes
end
def call
new_hash_article = {}
#fluxes.each do |flux|
url = flux.Url
rss = SimpleRSS.parse open(url)
#array_items = []
rss.channel.items.each do |item|
#array_items << item
end
#first = #array_items.first
calculator = 0
flux.articles.each do |article|
if article.Publication == #first.pubDate.to_s
calculator += 1
else
calculator += 0
end
end
if calculator == 0
article = Article.new
article.Title = #first.title
article.Description = #first.description
article.Url = #first.link
article.Publication = #first.pubDate
article.Lu = 0
article.flux_id = flux.id
article.save
new_hash_article[flux] = article
end
end
return new_hash_article
end
end
My view actu.js.erb
jQuery('#flux<%= #flux.id %>').append('<%= j render 'articles/show',
article: #article %>');
I don't if it's usefull but it's my articles/show:
<li id="<%= article.id %>">
<div class="content">
<p><%= article.Title %></p>
<a href="<%= article.Url %>" target="_blank" data="<%= article.id
%>">Voir l'article <i class="fas fa-arrow-right"></i></a>
<div id="switchlu" class="display">
<% if article.Lu == 0 %>
<%= link_to "Afficher comme Lu", articles_marklu_path(id:
article.id), :remote => true %>
<% else %>
<p><i class="fas fa-check"></i>Lu</p>
<%= link_to "Afficher comme non Lu", articles_markpalu_path(id:
article.id), :remote => true %>
<% end %>
</div>
</div>
</li>
The issue :
[1]: https://i.stack.imgur.com/WTZBu.png
Thanks for your time, and your help :)

Rails 5, simple javascript with form submit

I am hoping someone can help me here. Been at this for a few hours, but can't seem to figure out why my Javascript is not working on my simple form. I'm simply trying to display comments using the ajax call. I have gem 'jquery-rails', and required jquery, and jquery_ujs in my application.js file. Here's the code I have so far:
I have a Joy model that has_many comments.
<% #joys.each do |joy| %>
<ul id="comments-<%= joy.id %>">
<% joy.comments.where(void:'f').each do |comment| %>
<li><%= comment.body %></li>
<% end %>
</ul>
<%= form_with(model: [ joy.user, joy, joy.comments.build ], data:{ "js-comments-#{joy.id}" => true}) do |f| %>
<%= f.text_area :body, :class=>'form-control', :required=>'true' %>
<%= f.submit "Post Comment" %>
<% end %>
<script>
$(document).ready(function() {
$('[data-js-comments-<%= joy.id %>]').on("ajax:success", function(event, data, status, xhr){
$('#comments-<%=joy.id%>').append(xhr.responseText);
});
});
</script>
<% end %>
In my Comment controller, in my 'create' action, I have:
if #comment.save
render partial: "comment", locals: {comment: #comment}
end
In my Comment views, I created a partial, called _comment.html.erb:
<li>
<%= comment.body %>
</li>
So, now when I enter a comment, and click 'Post Comment', it correctly saves my Comment, but it does not ajax load the comment into list. Furthermore, the form does not refresh either. The text remains in the text box. It is not only until after I refresh the page when my comment shows up in the list. Anyone with any thoughts on what I'm missing or doing wrong???
Your help is greatly appreciated in advance.
form_with it's a remote form, you dont need that block <script>..</script>.
Just use create.js.erb then use jquery to append new comment.
And if you want to check if your message was created successfully, you can add a #status value in your controller.
//comments_controller.rb
def create
...
if #comment.save
#status = "success"
else
#status = "failed"
end
...
end
//create.js.erb - for example
$("#yourCommentList").append('<%= j( render partial: 'comments/comment', locals: #comment ) %>');
<% if #status == "success" %>
$("body").append(...your notification...)
...
<% else %>
...
<% end %>

Rails - Dynamically Login People

I have a rails app and when user clicks to login button on header a bootstrap popup modal opens with a form, asks for user email and password. When user types and presses enter, I use window.location.reload(); and the button login turns in to a button with a text says "Welcome <%= current_user.name %>"
What I want to do is, instead of using window location reload, can I update this dynamically?
Here is my sessions#create action
def create
user = User.find_by(email: params[:session][:email].downcase)
respond_to do |format|
if user && user.authenticate(params[:session][:password])
if user.activated?
log_in user
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
format.html { redirect_back_or user }
flash[:notice] = t('flash.sessions.create.success.html')
format.js #here I should do smth
else
format.html { redirect_to root_url }
format.json { render json: {email:['Account not activated. Check your email for the activation link.']} , status: :unprocessable_entity}
format.js { render json: {email:['Account not activated. Check your email for the activation link.']}, status: :unprocessable_entity }
end
then the create.js.erb
// close modal
$('#login-dialog').fadeToggle();
// clear form input elements
// todo/note: handle textarea, select, etc
$('form input[type="text"]').val('');
//Clear previous errors
$('.form-group.has-error').each(function(){
$('.help-block').html('');
$('.form-group').removeClass('has-error');
});
window.location.reload(); #here I am reloading the page then I can see login button disappears and new button saying Welcome Billy appears.
So how can I do that without reloading the window.
Thank you
EDIT
The thing is, I have also signup modal which user can click to open and these modal codes are in header.html.erb, when I render the page as you suggested it gives an error for sign up form;
<% modal ||= false %>
<% remote = modal ? true : false %>
<%= form_for(#user, remote: modal, :html => {role: :form, 'data-model' => 'user'}) do |f| %>
<div class="form-group">
<%= f.label :name, t('header.nameSurname') %>
<span class="help"></span>
<%= f.text_field :name, class: 'form-control' %>
<span class="help-block"></span>
</div>
<div class="form-group">
<%= f.label :username, t('header.username') %>
<span class="help"></span>
<%= f.text_field :username, class: 'form-control' %>
<span class="help-block"></span>
</div>
....
because of #user variable, if I change it to User.new is it ok?, would it create problem?.
I also have 3 different header partials. I normally render them in application.html.erb as;
<div id="render_main">
<% if #header_main %>
<%= render 'layouts/header_main' %> <!--Header comes here-->
<% elsif #header_listing %>
<%= render 'layouts/header_listing' %> <!--Header comes here-->
<% else %>
<%= render 'layouts/header' %>
<% end %>
</div>
But then in create.js.erb;
// close modal
$('#login-dialog').fadeToggle();
// clear form input elements
// todo/note: handle textarea, select, etc
$('form input[type="text"]').val('');
//Clear previous errors
$('.form-group.has-error').each(function(){
$('.help-block').html('');
$('.form-group').removeClass('has-error');
});
//window.location.reload();
<% if #header_main %>
$('#render_main').html('<%= j render "layouts/header_main"%>')
<% elsif #header_listing %>
$('#render_main').html('<%= j render "layouts/header_listing"%>')
<% else %>
$('#render_main').html('<%= j render "layouts/header"%>')
<% end %>
as I render it can not find #header_main variable I believe, so It does not work as it should be. How can I fix this?.
Main controller;
before_action :show_main_header, only: [:home]
def show_main_header
#header_main = true
end
Considering user login, from main controller home action. But it is probably because I actually run from session#create action. how can I fix it?
EDIT
firstly, thank you Rodrigo,
I have written a function to hold last action;
def location_action_name
if !logged_in?
url = Rails.application.routes.recognize_path(request.referrer)
#last_action = url[:action]
end
end
Then I write to create.js.erb;
<% if (#last_action == "home") %>
$('#render_main').html('<%= j render "layouts/header_main"%>')
<% elsif (#last_action == "listings") %>
$('#render_main').html('<%= j render "layouts/header_listing"%>')
<% else %>
$('#render_main').html('<%= j render "layouts/header"%>')
<% end %>
and worked! in case anyone wonders..
Let's say that you have an partial view for render the header (app/views/shared/_header.html.erb), what you need to do is rerender this partial and replace the header html:
create.js.erb
// window.location.reload();
$('#header-container').html('<%= j render "shared/header"%>')
EDIT:
If the #header_main and #header_listing variables are used to render the header partial, you'll need to instantiate them in your sessions#create action.
To do this, add the show_main_header filter to SessionsController too.

js.erb file is not been rendered

I'm trying to do an Ajax call on Ruby on Rails. When I select 2 collection_select's the third has to be rendered by Ajax. I'm new to Ruby on Rails, so if anybody could help me, I'd be thankful.
_form.html.erb:
<%= form_for(#preco_servico) do |f| %>
<div class="field">
<%= f.label :produto %>
<%= collection_select(:preco_servico, :produto, Produto.order('tipo'), :tipo, :tipo) %>
</div>
<div class="field" >
<%= f.label "Análise" %>
<%= collection_select(:preco_servico, :analise, TipoAnalise.order('tipo'), :tipo, :tipo) %>
</div>
<div class="field" id="parametro-select", :remote >
</div>
...
<% end %>
application.js:
jQuery(function($) {
$("#preco_servico_analise").change(function() {
var produto_id = $('select#preco_servico_produto :selected').val();
var analise_id = $('select#preco_servico_analise :selected').val();
$.get('/preco_servicos/update_parametro/' + produto_id + '/' + analise_id, function(data){
$("#parametro-select").html(data);
})
return false;
});
})
The method on controller:
def update_parametro
#precos = PrecoServico.where(:analise => params[:analise], :produto => params[:produto])
#sub_parametros = []
#precos.each do |preco|
#sub_parametros = Parametro.where("nome NOT IN (?)", preco.parametro)
end
respond_to do |format|
format.js
end
end
I've already included the code below on application.html.erb:
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
And the file update_parametro.js.erb:
sub_parametro <%= collection_select(:preco_servico, :parametro, #sub_parametros, :nome, :nome) %>
On console I get this:
Started GET "/preco_servicos/update_parametro/produto2/analise2"
for 127.0.0.1 at 2014-01-28 23:25:21 -0200 Processing by
PrecoServicosController#update_parametro as / Parameters:
{"preco_servicos"=>"preco_servicos",
"update_parametro"=>"update_parametro", "produto"=>"produto2",
"analise"=>"análise2"} PrecoServico Load (0.2ms)
SELECT preco_servicos.* FROM preco_servicos WHERE
preco_servicos.analise = 'análise2' AND preco_servicos.produto
= 'produto2' Rendered preco_servicos/update_parametro.js.erb (0.5ms) Completed 200 OK in 8ms (Views: 6.0ms | ActiveRecord: 0.2ms)
It tells me it is rendered, but nothing changes on screen and nothing appears in firebug.

Why does my js.erb file only run in one of these situations?

I have the following action on my controller for a Comment:
def create
#comment = comment.new(params[:comment])
#comment.replyable_type = params[:replyable_type]
#comment.replyable_id = params[:replyable_id]
#comment.user = current_user
respond_to do |format|
format.html do
# Removed
end
format.js do
#comment.save
end
end
end
and the following create.js.erb file for when it gets called by a remote form:
console.log('It did run');
<% if #comment.errors.any? %>
<% #comment.errors.full_messages.each do |msg| %>
console.log('<%= javascript_escape(msg) %>');
<% end %>
<% else %>
comment = "<%= escape_javascript render #comment %>";
<% if #comment.replyable_type == 'Comment' %>
$('#comment-<%= #comment.id %> > .replies').prepend(comment));
<% else %>
$('.comments').prepend(comment);
<% end %>
// removed
<% end %>
Along with the following form partial:
<%= form_for(Comment.new, url: comments_path, remote: true) do |f| %>
<div class="comment-form" id="comment-<%= replyable_type %>-<%= replyable_id %>">
<%= f.text_area :content, cols: 60, rows: 5 %>
<%= hidden_field_tag :replyable_id, replyable_id %>
<%= hidden_field_tag :replyable_type, replyable_type %>
<%= f.submit 'Send Comment', class: 'btn btn-primary' %>
</div>
<% end %>
replyable is a polymorphic association, which can be either a Post or a Comment object. When I submit a copy of the form on a page for a post, where replyable_type is Post and replyable_id is a post's ID, it works fine. When I submit a copy of the form on the same page, with the replyable_type set to Comment, and the replyable_id set to a comment's ID, the view the javascript does not run, at all. The action on the controller runs, using Firebug I can see the rendered javascript being sent back in response to the post request, and the comment is added to the database.
There are no errors in either the Rails console for generating the javascript or in the Firebug console to do with running the generated javascript. There are also no errors in the #comment.errors array. Even the first console.log in the Javascript is not run when the replyable object is a comment, despite being present in the rendered javascript.
What could cause this? I am using Rails 3.2.13 on Ruby 1.9.3

Categories

Resources