observe_field

I have the following in my view:

<%= observe_field 'guarantee_status', :url => {:controller =>
'testcontroller', :action => 'change_status'}, :with => 'value' %>
<div id="balance_div" style="display:none">
  <p>
    <b>Remaining Balance</b>
    <%= f.text_field :balance %>
  </p>
</div>

No when I first load this page, I need the change_status method hit on
my controller. It's only hit if I actually change the "guarantee_status"
field.

here's the method in my controller:

def change_status
    if request.xhr?
      render :update do |page|
        if params[:value].blank? || params[:value] == 'Due'
          page[:balance_div].hide
        else
          page[:balance_div].show
        end
      end
    end
  end

Allen Walker wrote:

I have the following in my view:

<%= observe_field 'guarantee_status', :url => {:controller =>
'testcontroller', :action => 'change_status'}, :with => 'value' %>
<div id="balance_div" style="display:none">
  <p>
    <b>Remaining Balance</b>
    <%= f.text_field :balance %>
  </p>
</div>

No when I first load this page, I need the change_status method hit on
my controller. It's only hit if I actually change the "guarantee_status"
field.

here's the method in my controller:

def change_status
    if request.xhr?
      render :update do |page|
        if params[:value].blank? || params[:value] == 'Due'
          page[:balance_div].hide
        else
          page[:balance_div].show
        end
      end
    end
  end

One way is to add the following below balance_div:

<%= javascript_tag "$('guarantee_status').onchange()" %>

Another would be to only render display:none into the
div tag if the condition is met.

The first method is preferred because when a page is
refreshed in Firefox it does not reset form entries,
but your app is still called as a simple GET, so the
div may be inappropriately made visible or hidden.

Allen Walker wrote:

Doesn't work. I tried putting the javascript_tag right after the div and outside the form itself. I understand the logic in the code but for some reason the onchange event is not causing the "change_status" to get fired. I even checked the development.log and change_status is not getting called.

OK, try this:

<%= javascript_onload "$('guarantee_status').onchange()" %>

using the following helper:

   def javascript_onload(js)
     javascript_tag <<-END
       olf = function() { #{js} };
       if (document.addEventListener)
         window.addEventListener("load", olf, false);
       else
         window.attachEvent("onload", olf);
     END
   end

No such luck again. Here's the generated HTML:

    <b>Status</b><br />
<select id="guarantee_status" name="guarantee[status]"><option
value="Due">Due</option>
<option value="Paid" selected="selected">In Progress</option></select>
  </p>

<script type="text/javascript">
//<![CDATA[
new Form.Element.EventObserver('guarantee_status', function(element,
value) {new Ajax.Request('/licensors/change_status', {asynchronous:true,
evalScripts:true, parameters:'value=' + encodeURIComponent(value)})})
//]]>
</script>
<div id="balance_div" style="display:none">
  <p>
    <b>Remaining Balance</b><br />
    <input id="guarantee_balance" name="guarantee[balance]" size="30"
type="text" value="2430.0000" />
  </p>
</div>

<script type="text/javascript">
//<![CDATA[
       olf = function() { $('guarantee_status').onchange() };
       if (document.addEventListener)
         window.addEventListener("load", olf, false);
       else
         window.attachEvent("onload", olf);

//]]>

</script>

Mark Reginald James wrote:

Allen Walker wrote:

No such luck again. Here's the generated HTML:

Looking at the Prototype code, observe only calls
the function if the value has actually changed.

So one way would be to move the observer inline:

:onchange => remote_function(:url => ...)

Or in this case it would be faster & simpler to keep
everything client-side:

function display_balance(gstatus) {
   if (gstatus == '' || gstatus == 'Due')
     $("balance_div").hide();
    else
      $("balance_div").show();
}

:onchange => 'display_balance(value)'

<%= javascript_tag "$('guarantee_status').onchange()" %>

Mark Reginald James wrote:

Allen Walker wrote:

No such luck again. Here's the generated HTML:

Looking at the Prototype code, observe only calls
the function if the value has actually changed.

So one way would be to move the observer inline:

:onchange => remote_function(:url => ...)

Or in this case it would be faster & simpler to keep
everything client-side:

function display_balance(gstatus) {
   if (gstatus == '' || gstatus == 'Due')
     $("balance_div").hide();
    else
      $("balance_div").show();
}

:onchange => 'display_balance(value)'

<%= javascript_tag "$('guarantee_status').onchange()" %>

--
Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com

Trying the client side I did:

<%= f.select :status, [['Due','Due'],['In Progress','Paid']], {},
{:onchange => 'display_balance(value)'} %>

and played in application.js:

function display_balance(gstatus) {
    if (gstatus == '' || gstatus == 'Due')
        $("balance_div").hide();
    else
        $("balance_div").show();
}

Generated HTML:

<select id="guarantee_status" name="guarantee[status]"
onchange="display_balance(value)"><option value="Due">Due</option>
<option value="Paid" selected="selected">In Progress</option></select>
  </p>

<div id="balance_div" style="display:none">
  <p>
    <b>Remaining Balance</b> )<br />
    <input id="guarantee_balance" name="guarantee[balance]" size="30"
type="text" value="2430.0000" />
  </p>
</div>

It doesn't work. I'm sure I'm missing something. I'm pretty unskilled of
javascript

Allen Walker wrote:

Trying the client side I did:

<%= f.select :status, [['Due','Due'],['In Progress','Paid']], {}, {:onchange => 'display_balance(value)'} %>

and played in application.js:

function display_balance(gstatus) {
    if (gstatus == '' || gstatus == 'Due')
        $("balance_div").hide();
    else
        $("balance_div").show();
}

Generated HTML:

<select id="guarantee_status" name="guarantee[status]" onchange="display_balance(value)"><option value="Due">Due</option>
<option value="Paid" selected="selected">In Progress</option></select>
  </p>

<div id="balance_div" style="display:none">
  <p>
    <b>Remaining Balance</b> )<br />
    <input id="guarantee_balance" name="guarantee[balance]" size="30" type="text" value="2430.0000" />
  </p>
</div>

It doesn't work. I'm sure I'm missing something. I'm pretty unskilled of javascript

Allen, that should work for normal select changes, but the
initial state won't be set unless you add a javascript_tag
that calls either the onchange function or the display_balance
function directly.

I'd recommend that you install a Javascript debugger like
Firebug to work out what's going on.

Even if I do:

<%= javascript_tag "alert('Hello')" %>

Nothing happens. So it doesn't seem to be executing this javascript
after the dom loads in the brower (so I still can't set the initial
state)

Mark Reginald James wrote:

Ok this worked:

<%= javascript_tag
"document.getElementById('guarantee_status').onchange()" %>

Allen Walker wrote:

Allen Walker wrote:

Ok this worked:

<%= javascript_tag
"document.getElementById('guarantee_status').onchange()" %>

That suggests your problem was absence of the Prototype
library, meaning that your AJAX call wouldn't have worked
either. Do you have something like:

<%= javascript_include_tag "prototype", "application" %>

?

Mark Reginald James wrote:

Allen Walker wrote:

Ok this worked:

<%= javascript_tag
"document.getElementById('guarantee_status').onchange()" %>

That suggests your problem was absence of the Prototype
library, meaning that your AJAX call wouldn't have worked
either. Do you have something like:

<%= javascript_include_tag "prototype", "application" %>

?

--
Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com

Yeah something was wrong with my

<%= javascript_include_tag :defaults %>

Got that fixed.

Regardless I had to go pure client side to get to onchange to fire
properly. But I did get it to work.

Thanks for your help