Search code examples
jqueryruby-on-railsfacebox

Rails/Facebox - update with remote function


Have searched on this issue and haven't been able to find a solution.

I have a form with elements that are replaced by partials depending on the selection of prior elements in the form (for example - once a user has selected an "Origin" the form will update the "Destinations" collection_select with any destination available from the selected origin). This works fine.. except I would like the form to be displayed modally in a Facebox popup.

Currently the facebox popup loads the form correctly however no onchange actions on the form elements seem to be updating...

In View:
<%= link_to "New Delivery", new_delivery_requests_path, :remote => true %>

Remote call (views/delivery_requests/new.js.erb):
$.facebox('<%= escape_javascript(render 'new') %>')

New layout (views/delivery_requests/new.html.erb):

<%= form_for @price_update do |f| %>
    <% if @price_update.errors.any? %>
    <h2>Errors:</h2>
    <ul>
        <% @price_update.errors.full_messages.each do |message|%>
        <li><%= message %> </li>
        <% end %>
    </ul>
    <% end %>
    <br />
    <table>
        <tr> 
            <td><%= f.label "Select origin location: "%> </td> 
            <td><%= collection_select(:route, :origin_id,  @origins,  :id, :name, 
            { :prompt   => "Please select an origin" },
            { :onchange => "#{remote_function(
                :url  => { :action => "update_destinations"}, 
                :with => "'origin_id='+value")}",
                :id => "origin_select"} )%>
            </td>
        </tr>
        <tr>
            <td><%= f.label "Select destination location: "%> </td>
            <td><div id="destinations">
                <%= collection_select(:route, :destination, 
                @available_routes, :id, :destination, 
                { :prompt   => "Please select an origin first" }, { :disabled => "disabled" })%></div></td>
        </tr>               
        <tr>
            <td><%= f.label "Current Prices: "%> </td>
            <td>
                <div id="current-prices-table"></div>
            </td>
        </tr>   
        <tr>
            <td><%= f.label "Please select price option" %></td>
            <td>
                <div id = "price-selection"></div>
            </td>
        </tr>
        <tr>
            <td><%= f.label "Priority" %></td>
            <td><%= f.label "Price Per Gram" %></td>
            <td><%= f.label "Price per cm3" %></td>
        </tr>
        <tr>
            <td><div id="priority-label"></div></td>
            <td><%= f.text_field :new_price_per_gram, :id => "price_per_gram_textfield" %></td>
            <td><%= f.text_field :new_price_per_vol, :id => "price_per_vol_textfield" %></td>
        </tr>
    </table>
    <br />
    <%= f.submit "Update Prices"%>  
<% end %>

And the update destinations action in delivery_requests controller:

def update_destinations
    # updates the available list of destinations after an
    # origin location has been chosen when making a new delivery request
    sel_origin = Location.find(params[:origin_id])
    @available_routes = Route.find_available_routes(sel_origin.name)
    render :update do |page|
      page.replace_html 'destinations', :partial => 'destinations_select', :object => @destinations
    end
  end

I am fairly new to rails - any advice would be appreicated.


Solution

  • I've been struggling with this myself tonight and finally came up with an answer. You need to reference the facebox you have open. This is what you would do to make your stuff work.

    def update_destinations
    # updates the available list of destinations after an
    # origin location has been chosen when making a new delivery request
    sel_origin = Location.find(params[:origin_id])
    @available_routes = Route.find_available_routes(sel_origin.name)
    render :update do |page|
        page << "jQuery('#facebox .content #destinations').replaceWith(#{(render :partial => 'destinations_select', :object => @destinations).to_json})"       
    end
    end
    

    I have to thank jQuery .on not working with dynamic DOM/HTML which led me to https://github.com/ihower/facebox_render/blob/master/lib/facebox_render.rb where I constructed the answer.