Where to store view parameters in an AJAX session? - ruby-on-rails

In a non-AJAX web app, the URL would contain my view parameters (e.g. mysite?page=2&sort=name). In an AJAX app, where do I store the same info? In the Session object?

I'm assuming you want to know how to pass additional params with an AJAX call. This really depends on how you're formulating the AJAX call.
If you're using the built-in Rails helpers, you can pass additional params inside the url_for helper. For example, lets say that you have a products route and you want to AJAX load a list of all products. The link_to helper might look something like this (Rails 3.2)
link_to "All Products", products_path(:page => 2, :sort => "name"), :remote => true
If on the other hand you're using a JavaScript framework like jQuery, you can pass additional params using the data option. For example
$.ajax({
url: "/products",
data: {
page: 2,
sort: "name"
},
success: function(data) {
// handle success
},
failure: function(data) {
// handle failure
}
});
Storing this data (page, sort, etc.) can be done multiple ways also. The easiest way would be to store this data inside a JavaScript variable.
window.page = 2;
window.sort = "name";
Another solution is to store this information in the data attribute of a particular DOM element on the page. For example, if you have a <div id='products'> that contains a list of the paginated, sorted products, you could store the information like this (jQuery)
$("#products").data("page", 2);
$("#products").data("sort", "name");

Generally speaking, you don't structure you're requests differently for AJAX in Rails. You'll just add the :remote => true attribute to your link or form, then make the controller action respond_to js
respond_to do |format|
format.js
end
And then put your_action.js.erb in your views and write javascript that updates the dom in the appropriate way.

Related

How to update/pre-populate Rails form using a dropdown

I am trying to create a form with dropdown where users can create a new object if something like "Create new" is selected, or they have the option of choosing from their previously created objects, which should prefill the form with the corresponding data.
At the moment I simply have a for each loop filling the dropdown list with the previously created objects which is outside the form, and a form that creates new objects.
How can I make this form dynamic so that when a previously selected object is selected, the form pre-fills and allows for editing?
You'd have to send out an AJAX GET request to a custom route and then have a controller action that responds to json format and returns a collection based on params passed in that GET request. Say, you are loading available car models based on a selected make:
routes:
get '/get_models/:make_id', to: 'car_makes#available_models'
controller action:
def available_models
#models = Model.where(id: ids)
respond_to do |format|
format.json { render json: #models }
end
end
AJAX request:
var fetchModels = function(makeId){
$.ajax({
method: 'GET',
url: '/get_models/' + makeId,
success: function(data) {
...
var target = $('select#car_models'); // field to which options are appended
$.each(data, function(id, model){
$(target).append(
$('<option>').text(model).attr('value', id) // populate options );
});
}
...
});
}
and then setting the AJAX request to fire on .change event in a parent select field:
$('select#car_makes').change(function(){
var makeId = $(this).val();
fetchModels(makeId);
});
There are a number of resources explaining other ways to achieve this:
https://gorails.com/episodes/jquery-ujs-and-ajax
http://railscasts.com/episodes/88-dynamic-select-menus-revised
So I ended up looping through all of the potential options for the select dropdown, and looping through the edit rails form with all the potential options, and using jQuery onchange to show / hide the correct html.
This doesn't feel like a very good solution to me, especially as it has to load the html of all the options every time.. but I don't know what else to do and it works.
If anyone has any ideas for a better solution, let me know :)

Is their any way?I could get the value of dropdown to use in controller using onchange event handler in ruby on rails application

I want to call a method using onchange event handler when a user changes the value on a dropdown.Below is the code for my dropdown box.
<%= select_tag :name,options_for_select(#tests.map{|u| [u.name]}.uniq),:onchange => 'update_dropdown(:name)' %>
In the controller i want a method.which takes the value of selection in dropdown as paramater:
Below code searches database for the document with value of the parameter given from view.And return the document.What are the changes i have to make to get the selection in the controller as the dropdown values are changed!
def update_dropdown(name)
#drop = Test.where("name" => name)
end
How to get the selection value from view into the controller as parameter?
I has a mongoDatabase with documents(row) consisting key named:name.I has 4 unique values under key name.I want user to select the value using dropdown.As the user selected the dropdown.Without page refresh the documents consisting values selected with the key name should be displayed.
Ex:under key name.I has four values for 200 documents.named:
["value1","value2","value3","value4"].These values are the options
for dropdown menu.If user selected any of the values.The documents consisting value for key name should be displayed.
All you need to make ajax call on onchange event. Here is a link to a helpful answer
stackoverflow.com/a/7952315/4136098
How to get the selection value from view into the controller as parameter
Only way is to send the data through either an HTTP or Ajax (XML) request.
Because you've not explained your user story very well, I'll explain the overall schematics on how to get it to work...
Stateless
HTTP makes Rails applications stateless - meaning that each time you send interactions to it, it will have to rebuild the user environment each time (this is why sessions are so important to Rails).
This means that each time you want to invoke new actions / methods, you have to send a request to your server. The request can be sent over several protocols (HTTP, XML and Websockets) - each has the same pattern: Request > Logic > Output
Thus, if you want to send data to your controller, you'll have to either have a full page refresh (follow the above pattern), or send the data via ajax.
Ajax
In this case I'd recommend using ajax to send a request to your controller.
# View
<%= select_tag :name,options_for_select(#tests.map{|u| [u.name]}.uniq), id: "select" %>
#app/assets/javascripts/application.js
$(document).on("change", "#select", function(e) {
$.get("/controller/update_dropdown", {id: $(this).val() }, function(data) {
# Do something here
});
});
This will allow you to use the following:
#config/routes.rb
resources :controller do
get :update_dropdown, on: :collection #-> url.com/controller/update_dropdown
end
#app/controllers/controller_controller.rb
class ControllerController < ApplicationController
def update_dropdown
# params[:id] will be available
#test = Test.find params[:id]
render json: #test.to_json
end
end

how to send remote form params

I have a form which is using several input fields being ajaxified with remote: true and custom controller actions. This way UJS driver sends only given form input as params. What I want to accomplish is an ajaxified input field which will send value of a field outside of it's "scope" as params. What do you suggest?
Let me explain the whole flow of the ajax-rails and remote=> true and you can do this with that following way and you can get all the params in your method.
first when you used the remote=> true then the form will submit or call the action which you have define in form like here is an example:
<%= form_tag({:controller => 'my', :action => 'my_data'},:id => 'filter_form', :remote => true) do %>
#code here
<%= submit_tag 'save', :name => 'commit'%>
<%end%>
now above code will go to my_data action in my controller,
here you can define the respone type with
def my_data
#actions on data here
respond_to do |format|
format.js
end
now you have to made a .js file with named as action name....
my_data.js.erb
here the whole affect of form you can write and update document element through jquery and javascript.
For every input you just assign a class and write a method that call when the input box will change.One more thing that when you wants to do in a single method the every input have a unique ID, send that also in params and do task what ever you wants to do.
Rails' JQuery UJS is just a dependency which Rails uses to call ajax requests on your behalf. This means your question is not particularly to do with JQuery UJS, but with how to handle it with ajax overall
You'll typically handle any extra data by appending it to the Ajax request:
<%= link_to "Link", new_post_path(params: "here"), remote: true %>
If you want to create an "ajaxified" field, you'll probably have to use a manual ajax call to capture the change event, allowing you to send the data to your event:
#app/assets/javascripts/application.js
$('input[name="element"]').on("change", function(){
$.ajax({
url: "url",
data: $(this).serialize()
});
});
Then, as mentioned by #baharat Soni, you'll be able to handle the request on the server using respond_to

Adding rendered HTML to JSON

Given a controller MapsController:
class MapsController < ApplicationController
def index
#campings = Camping.finm(:all) #in reality a much more complex scope.
respond_to do |format|
format.html
format.json { render :json => #campings }
end
end
end
This renders the JSON just fine. But now, I'd like to pass along some HTML to inject into the DOM:
$.ajax({
dataType: "json",
url: "maps.json?bounding=45.446465,-4.935988,53.944621,17.036668",
}).done(function (data) {
//...
var gInfoWindow = new google.maps.InfoWindow({
content: camping.infowindow
});
//...
$("#campings").append(camping.listing);
});
This JavaScript assumes a .listing and .infowindow attribute in each returned JSON-Object. They should contain HTML,
rendered with the partials campings/_infowindow.html.haml and campings/_listing.html.haml.
Is this the correct angle to tackle this? Or should I rather build the HTML within the JavaScript and avoid sending HTML? If so, is there still a way to use partials to build the actual HTML?
How can I add listing and infowindow to the ObjectsCamping model does not have these fields?
Maybe a bit rough (and not 100% super the "Rails way") but working fine for me in a similar situation:
render :text => {:result => "success",
:document_row => render_to_string(
:file => "admin/documents/_document_row",
:formats => "html",
:layout => false,
:locals => {:documentable => documentable})}.to_json
so roughly just generating a hash and use render_to_string to get the html from th _document_row template.
If you use something like KnockoutJS or another javascript data-binding or templating tool, you can have a skeleton 'template' in the page to start with, that gets filled in with camping listings when you make the ajax request.
The way it works is that you have your table or list or whatever of camping listings bound to an array of camping objects in your Knockout model. When you make your ajax request, you just update that array with the json that comes back. When that array is updated, the DOM is automatically updated to show the new listing. This lets your ajax request get the data only and not all the HTML markup, which means fewer bytes over the wire, and you can separate the act of fetching new data from updating the DOM based on that data.

Ruby/Rails/AJAX/JQuery - On link click, passing a parameter and performing a controller action

I'm trying to use clicking a link to perform and action in my controller called 'yes' but do so client side rather than having to refresh everytime a user clicks.
Before I had an link_to that routed to a action called "yes" and passed the id of a model I have called 'event'
<%= link_to "yes", yes_path(event)%> (in view)
match 'user/:id/yes' => 'user#yes', :as => "yes" {in routes.rb)
The problem issue is that every time the user clicks the link the page refreshes while it performs the yes action, so it will flow alot smoother if I can tell the backend to perform the actions client side.
S0 I found a reference here : execute controller/action from javascript in rails3
and took a look at the documentation : http://api.jquery.com/jQuery.ajax/
And came up with this. Where if the post is successful at the previous route from above change a css class for the link (change color).
$.ajax({
type: "POST",
url: "/user/" + $(this).attr('event') + "/yes/",
success: function(){
$(".like").click(function() {
if ($(this).hasClass("selected")) {
$(this).addClass("selected");
return false; }
});
I also added this is the bottom of the controller that the desired javascript is being used.
respond_to do |format|
format.html { }
format.js
end
So now my link_to looks like this
<%= link_to "yes", yes_path(event), :class => "like", :remote => true %>
But the page is still refreshing and It doesnt look like its calling the AJAX at all.
am I passing the parameter "event" properly as a jquery attribute?
am I calling the link_to properly?
This is my first time so I have no idea what I'm doing wrong, possibly a few things?
I'd really appreciate any help
Is this what you're after?
$(".like").click(function(evt) {
evt.preventDefault();
var $self = $(this);
$.post($self.attr("href"), function(response) {
$self.addClass("selected");
});
});
The first line binds the JavaScript to all elements with a class of like. preventDefault is the preferred way to prevent the default behavior of an anchor tag (navigate to the href). $.post() is shorthand for $.ajax({ type: "POST" }).
Whatever you want to happen after a successful post to the server goes that finally function call. The first argument is the response from the server.
Rich

Resources