How can I update a div value using Ajax but calling a function on the OnChange?

Hey guys,

I'm trying to update a div with a result coming from a request to the database.

So I have created this method on the controller

  def retrieve_part_price     @price = Part.find(params[:id])     respond_to do |format|       format.html { redirect_to(items_path)}       format.js { render :nothing => true }     end   end

and added it to the routes properly, but I don't know how should I call it from my view side to bring the value using Ajax.

any advice? blog post?

Thank you.

Kleber Shimabuku wrote in post #1015666:

any advice? blog post?

This works for me:

<h1>Users#new</h1> <p>Find me in app/views/users/new.html.erb</p>

<%= link_to "Click me",             {:controller => 'users', :action => 'get_info'},             :remote => true %>

<div id="update_me">Hello</div> <div>world</div>

You can make your js more general by doing this:

<h1>Users#new</h1> <p>Find me in app/views/users/new.html.erb</p>

<%= link_to "Click me",           {:controller => 'users',            :action => 'get_info',            :my_target => 'update_me'},

           :remote => true %>

<div id="update_me">Hello</div> <div>world</div>

Thank you guys, but as I said in the topic, I looking how to perform this on event OnChange of an <select>

Just updating:

I have this on a partial:

<p class="fields">   <%= f.collection_select(:part_id, @parts, :id, :title, { :prompt => true } , { :onchange => "load_part_price_select(this.id, this.options[this.selectedIndex].value);" } ) %>   <span class='part_price'> _ _ _ _ </span>   <%= f.hidden_field :_destroy %>   <%= link_to_remove_fields "remove", f %> </p>

and the relative function on application.js file:

function load_part_price_select(id, value) {   alert(id);   alert(value);   $('#' + id ).live('change',function() {       $.ajax({       url: value + '/retrieve_part_price/',       success: function(responseData) {         alert('test');       }     });   }); };

For now, I have to figure out a question about routes

I've created the right method on my ItemsController:

  def retrieve_part_price     @price = Part.find(params[:id])   end

and configured the routed as:

resources :items do   get 'retrieve_part_price', :on => :member end

but the development log shows me an error:

<!DOCTYPE html> <html> <head>   <title><%= @title %></title>   <%= csrf_meta_tag %>   <%= javascript_include_tag :defaults %>

<script type="text/javascript">     function update_info() {

        new Ajax.Updater( 'target_div',                           '/users/get_info',                           {                             method: 'get',                             parameters: {select_choice: $F("my_select")}                           }                         );

    }

    document.observe('dom:loaded', function() {           $("my_select").observe('change', update_info)       }); </script>

</head> <body>

  <%= yield %>

</body> </html>

Hi everyone,

Thank you all for the help. I pasted the final code on the pastebin so if someone else needs it someday it will be available for consulting.

and the form

<p class="fields">   <%= f.collection_select(:part_id, @parts, :id, :title, { :prompt => true } , { :onchange => "load_part_price_select(this.id, this.options[this.selectedIndex].value);" } ) %>   <%= f.label(:part_id, "Price: ") %>   <span class="price"></span>   <%= f.hidden_field :_destroy %>   <%= link_to_remove_fields "remove", f %> </p>

Kleber Shimabuku wrote in post #1015905:

and the form

<p class="fields">   <%= f.collection_select(:part_id, @parts, :id, :title, { :prompt => true } , { :onchange => "load_part_price_select(this.id, this.options[this.selectedIndex].value);" } ) %>   <%= f.label(:part_id, "Price: ") %>   <span class="price"></span>   <%= f.hidden_field :_destroy %>   <%= link_to_remove_fields "remove", f %> </p>

js shouldn't be in your html, i.e. this:

{ :onchange => "load_part_price_select(this.id,

this.options[this.selectedIndex].value);"

should be done up in the <head> section of your html. In order to do that, you have to put your js inside a function that executes after the page has loaded.

now with rails 3.1 doesn't all the java code go in a *.js.coffee file inside the app/assets/javascripts/ ? or do we write it on the corresponding view directly?

@7stud,

the "onchange" behavior make a function call, that's right, and this function (load_part_price_select() ) belongs to a js file, in this case I did put it on the application.js file.

this is actually working for me.

@Filippos,

I haven't installed rails 3.1 yet, still on 3.0.9 for now, so I can't tell you that, sorry.

Kleber Shimabuku wrote in post #1016065:

@7stud,

the "onchange" behavior make a function call, that's right, and this function (load_part_price_select() ) belongs to a js file, in this case I did put it on the application.js file.

Yeah, but you put the js that calls the function in the html here:

<p class="fields">   <%= f.collection_select(:part_id, @parts, :id, :title, { :prompt => true } , { :onchange => "load_part_price_select(this.id, this.options[this.selectedIndex].value);" } ) %>   <%= f.label(:part_id, "Price: ") %>

Doesn't that look like a bunch of chicken scratchings to you? You could make it 'look' better with some spacing, but the point is: mixing html and javascript is bad style. If you load that page in a browser and do a View Source, and then look at the <select> tag, it will have an onchange attribute.

Mixing html and js was considered bad style more than 7 years ago, and it remains bad style today. In fact, Rails 3 was redesigned so that when rails generates html pages, no js appears in the html pages. In your case, you are writing your own js(using jQuery), and you just foiled the rails teams hard work by explicitly writing your js in the html. You should watch this:

this is actually working for me.

Yes. It's horrible style though. css, js, and html should all be in separate files. If you examine the code I posted, this is what the html looks like:

<h1>Users#new</h1> <p>Find me in app/views/users/new.html.erb</p>

<div id="target_div">Hello world</div>

<select id="my_select">   <option value="mars">mars</option>   <option value="venus">venus</option> </select>

See any js in there?? Okay, I used prototype. Here it is with jquery:

<h1>Users#new</h1> <p>Find me in app/views/users/new.html.erb</p>

<div id="target_div">Hello world</div>

<%= form_for(@user) do |f|     f.collection_select(       :id,       @users,       :id,       :email,       { :prompt => true },       {         :id => "my_select",         :class => "cool_effects"       }     ) end %>

===app/views/layouts/application.html.erb:

<!DOCTYPE html> <html> <head>   <title><%= @title %></title>   <%= csrf_meta_tag %>   <%=   javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js&quot;,                          "jquery.rails.js"   %> <script type="text/javascript">

  $(document).ready(function () {

      $("#my_select").change(         function () {           var choice = $(this).val();                      //turn 'this', which is the select element,                      //into a JQuery collection object, which                      //has a val() method.

          var query_string = "select_val=" + choice + "&another_val=10";

          $("#target_div").load('users/get_info', query_string)         }       );

  });

</script>

</head> <body>

  <%= yield %>

</body> </html>

In this code:

function load_part_price_select(id, value) {         // alert(id);         // alert(value);         $('#' + id ).live('change',function() {             $.ajax({                   url: '/parts/' + value + '/price',                   type: 'get',                   context: this,                   dataType: 'script',                   success: function(responseData) {                     // alert('success: ' + responseData);                     $(this).nextAll("span.price:first").html(responseData);                   }                 });         }); };

...why do you have:

dataType: 'script',

I doubt your action is responding to the ajax request by sending a string with js code in it back to your page--because your action looks like this:

  def retrieve_part_price     @price = Part.find(params[:id])     respond_to do |format|       format.html { redirect_to(items_path)}       format.js { render :nothing => true }     end   end

It looks like you are trying to send a price back, so you should specify:

  dataType: 'text'

But then I don't understand how your action returns anything because you wrote this:

      format.js { render :nothing => true }

I think that should be render :text.