I'm using Rails 3.2.13, and then Nested_Form gem to create a shipment header record and multiple shipments detail records. Everything works great, I can add, remove detail line items and save correctly. What I'd like to do now is add some UJS or Ajax to the Material select box that's part of the nested fields_for section of the form. When a material is selected, the "Current Balance" label next to it would be updated with the correct inventory number for each line item.
This is my first foray into UJS and Ajax and I'm a bit lost on how to accomplish this task. Thus far the relevant part of my form looks this:
new.html.erb:
<div class="col-md-12 form-group">
<div class="panel panel-default">
<table class="table table-striped table-hover" id="details" >
<th>Material</th>
<th>Current Balance</th>
<th>Net Weight</th>
<th>Gross Weight</th>
<th></th>
<%= f.fields_for :downstreamDetails, :wrapper => false do |dd| %>
<tr class="fields">
<td><%= dd.select :tb_product_type_id, options_from_collection_for_select( @productTypes, :id, :product_type), { :prompt => "Select Material"} , {:class =>"form-control col-sm-2", :data => { remote: true, :url => url_for(:controller => 'downstreams', :action => 'getInventoryData', :paroductType => @productType ,format: 'js') } } %></td>
<td nowrap="true"><label> <%= number_with_delimiter(@currentBal) %> lbs</label></td>
<td><%= dd.text_field :ship_total_net_weight, :class =>"form-control col-sm-2" %></td>
<td><%= dd.text_field :ship_total_gross_weight, :class =>"form-control col-sm-2" %></td>
<td><%= dd.link_to_remove "Remove", :data => {:target => "#details"}, :class => "btn btn-primary btn-small btn-block" %></td>
</tr>
<% end %>
</table>
</div>
<div class="row">
<div class="col-md-2"><%= f.link_to_add "Add Material" ,:downstreamDetails, :data => {:target => "#details"}, :class => "btn btn-primary btn-small btn-block" %></div>
</div>
</div>
<div class="row" >
<div class="col-md-9"></div>
<div class="col-md-3"><%= f.submit "Submit", class: "btn btn-small btn-primary" %></div>
</div>
<% end %>
</div>
and my controller action:
def getInventoryData
@tb_product_type = Downstream.new(params[:downstream])
@product_id = @tb_product_type.downstreamDetails.first.tb_product_type_id
@product = ProductType.find(@product_id)
@downstream_ids = Downstream.select("id").where(:to_company_id => current_user.company_id, :is_verified => true).accessible_by(current_ability)
@currentBal = DownstreamDetail.select("sum(receive_total_net_weight) as currentBal").where(:downstream_id => @downstream_ids, :tb_product_type_id => @product )
respond_to do |format|
format.html { redirect_to create_url }
format.js
end
end
I have a getInventoryData.js.erb but am currently at a loss for what to put in it. Currently it just gives an alert, which works.
The questions I have are:
Is there a way to submit just the tb_product_type_id when a material is selected from the select box? Currently, I have to navigate through the params via params[:downstream] (the parent record) to get the id. I'd like to just be able to say @tb_product_type_id = param[:tb_product_type_id] in the controller action
I don't think the existing code that uses @currentBal in the controller and the view will work when I add more than one line item... how can I refactor it to handle one or more line items?
What do I need in my getInventory.js.erb file to correctly change the label for the "Current Balance" column knowing that I'll have to handle multiple line items? (Remember I'm using Nested_Form Gem)
Am I headed in the right direction or is there another way to go about this that's much easier/cleaner?
Thanks in advance!
UPDATE
I've got everything working except the getInventory.js.erb file, still looking for help here. Was able to get the "Current Balance" label to be updated on the first line item but as I originally suspected it didn't work on the multiple line items. So I changed the controller code to grab the totals for all materials like this:
def getInventoryData
@downstream_ids = Downstream.select("id").where(:to_company_id => current_user.company_id, :is_verified => true).accessible_by(current_ability)
@currentBals = DownstreamDetail.select("tb_product_type as material, sum(receive_total_net_weight) as currentBal").where(:downstream_id => @downstream_ids).group(:tb_product_type)
respond_to do |format|
format.html { redirect_to create_url }
format.js
end
end
With this controller code I think I just need to be able to iterate through the result set and match it with the selected material, then update the label tag that directly follows in the select tag. Thats where I'm still struggling, How can I use jquery to navigate the DOM and find the correct label to update? I've used this javascript to find all select box values but I can't seem to get the next element and update it:
$('select > option:selected').each(function() {
alert($(this).text() + ' ' + $(this).val());
<% @currentBals.each do |c| %>
if( $(this).text() == '<%= c.material %>' ) {
alert(document.getElementById($(this).parent()))
$(this).parent().next("label").innerHTML = "<%= number_with_delimiter(c.currentBal) %> lbs"
alert("<%= c.material %>");
}
<% end %>
});