Rails 3.2.13 Nested_Form Gem использует UJS или Ajax для обновления метки во вложенной форме

Я использую Rails 3.2.13, а затем гем Nested_Form для создания записи заголовка отгрузки и нескольких подробных записей о доставке. Все отлично работает, я могу добавлять, удалять детализированные позиции и правильно сохранять. Что я хотел бы сделать сейчас, так это добавить немного UJS или Ajax в поле выбора материала, которое является частью вложенного раздела fields_for формы. Когда материал выбран, метка «Текущий баланс» рядом с ним будет обновлена ​​​​с правильным инвентарным номером для каждой позиции.

введите здесь описание изображения

Это мой первый набег на UJS и Ajax, и я немного не понимаю, как выполнить эту задачу. Пока соответствующая часть моей формы выглядит так:

новый.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>

и мое действие контроллера:

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

У меня есть getInventoryData.js.erb, но я не знаю, что в него добавить. В настоящее время он просто выдает предупреждение, которое работает.

У меня есть вопросы:

  • Есть ли способ отправить только tb_product_type_id, когда материал выбран из поля выбора? В настоящее время мне нужно перемещаться по параметрам через params[:downstream] (родительская запись), чтобы получить идентификатор. Я хотел бы просто сказать @tb_product_type_id = param[:tb_product_type_id] в действии контроллера

  • Я не думаю, что существующий код, который использует @currentBal в контроллере и представлении, будет работать, когда я добавляю более одного элемента строки... как я могу реорганизовать его для обработки одного или нескольких элементов строки?

  • Что мне нужно в моем файле getInventory.js.erb, чтобы правильно изменить метку для столбца «Текущий баланс», зная, что мне придется обрабатывать несколько позиций? (Помните, что я использую Nested_Form Gem)

  • Я двигаюсь в правильном направлении или есть другой способ сделать это намного проще/чище?

Заранее спасибо!

ОБНОВЛЕНИЕ

У меня все работает, кроме файла getInventory.js.erb, все еще ищу здесь помощи. Удалось обновить метку «Текущий баланс» для первой позиции, но, как я изначально подозревал, она не работала для нескольких позиций. Поэтому я изменил код контроллера, чтобы получить итоговые значения для всех материалов следующим образом:

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

Я думаю, что с этим кодом контроллера мне просто нужно иметь возможность перебирать набор результатов и сопоставлять его с выбранным материалом, а затем обновлять тег метки, который следует непосредственно за тегом выбора. Вот где я все еще борюсь. Как я могу использовать jquery для навигации по DOM и найти правильную метку для обновления? Я использовал этот javascript, чтобы найти все значения поля выбора, но я не могу получить следующий элемент и обновить его:

$('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 %>    

});

person user2967603    schedule 17.04.2014    source источник


Ответы (1)


Итак, принимая во внимание обновление, которое я сделал ранее (в частности, для кода контроллера), я решил эту проблему, используя гем nested_form, как было заявлено изначально, и ajax+UJS. Последним кусочком головоломки стал следующий код в моем файле getInventory.js.erb:

$( ".fields" ).each( function(){    
    <% @currentBals.each do |c| %>
        if( $(this).find("option:selected").text() == '<%= c.material %>' ) {   
            $(this).find("label").html("<%=  number_with_delimiter(c.currentBal) %> lbs")   
        }
    <% end %>    

});

Мне пришлось пройтись по элементам в классе «fields» (требуется вложенной_формой), найти выбранный параметр в каждом элементе строки, сравнить его с каждым элементом в хэше currentBals, заполненном в действии контроллера. Когда материалы совпадают, я затем обновляю тег этикетки, непосредственно примыкающий к полю выбора, с правильным балансом.

Надеюсь, это поможет любому, кто плохо знаком с ajax/ujs, как и я, или попытается добавить немного дополнительной функциональности к тому, что уже встроено в gemnested_form.

person user2967603    schedule 23.04.2014