Forum: Ruby on Rails observe_field

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-20 23:16
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
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2008-10-21 00:20
(Received via mailing list)
Allen Walker wrote:
>
>           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.

--
Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-21 00:36
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.


Mark Reginald James wrote:
> Allen Walker wrote:
>>
>>           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.
>
> --
> Rails Wheels - Find Plugins, List & Sell Plugins -
> http://railswheels.com
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2008-10-21 01:21
(Received via mailing list)
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

--
Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-21 01:33
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:
>> 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
>
> --
> Rails Wheels - Find Plugins, List & Sell Plugins -
> http://railswheels.com
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2008-10-21 03:57
(Received via mailing list)
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
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-21 04:36
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
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2008-10-21 05:08
(Received via mailing list)
Allen Walker wrote:

>     else
> <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.

--
Rails Wheels - Find Plugins, List & Sell Plugins -
http://railswheels.com
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-21 06:03
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:
> Allen Walker wrote:
>
>>     else
>> <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.
>
> --
> Rails Wheels - Find Plugins, List & Sell Plugins -
> http://railswheels.com
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-21 06:14
Ok this worked:

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


Allen Walker wrote:
> 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)
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2008-10-21 10:47
(Received via mailing list)
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
98fa0eec8815e726d1b9f46f609004f8?d=identicon&s=25 Allen Walker (auswalk)
on 2008-10-21 18:23
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
This topic is locked and can not be replied to.