NicSlim
NicSlim

Reputation: 339

Sorting nested form fields in rails

I'm trying to create an inventory form that sorts the products based on their category. Ideally I'll be able to have these products listed by category, and will put in some javascript to hide/show products of a given category.

Currently, I'm having trouble wrapping my head around how to split my products up by category in my form. Here's what I currently have (modeled after Ryan Bates' Railscasts for nested attributes):

class InventoriesController < ApplicationController
 def new
  @title = "Take Inventory"
  @vendor = ProductVendor.find(params[:product_vendor_id])
  @inventory = Inventory.new()
  @products = @vendor.products.active
   @products.each do |product|
    @inventory_line_item = @inventory.inventory_line_items.build({:product_id =>    product.id})
   end
 end

My form for a new inventory:

<%= form_for @inventory do |f| %>
 <table>
  <tr>
   <th>Item</th>
   <th>Quantity</th>
  </tr>

 <% f.fields_for :inventory_line_items do |builder| %>

 <tr>
  <td><%= builder.object.product.name %></td>
  <td><%= builder.text_field(:quantity, :size => 3) %></td>
      <%= builder.hidden_field :product_id %>
 </tr>

 <% end %>

 </table>
 <%= f.hidden_field(:user_id, :value => current_user.id) %>
 <%= f.hidden_field(:location_id, :value => current_location.id) %>
 <%= f.hidden_field(:product_vendor_id, :value => @vendor.id) %>

 <%= f.submit "Submit" %>

 <% end %>

So I have another model called product_category that has_many products. How do I sort and separate my products by category in the controller and form? Also, is there a way to do this using Formtastic? Thanks!

Upvotes: 4

Views: 2191

Answers (1)

Marc
Marc

Reputation: 2584

It's actually pretty simple to implement. Add a hidden field in the nest_form field with the attribute position (add this attr to your model of course) and add this to your js along with using the jquery-ui.js

  $('#task_fields').sortable({
    items: '.fields',
    dropOnEmpty: true,
    cursor: 'move',
    handle: '.move',
    opacity: 0.4,
    scroll: true,
    axis:'y',
    placeholder: 'ui-state-highlight',
    start: function(e, ui) {
      ui.placeholder.height(ui.item.height());
    },
    update: function() {
      $(this).children(".fields").each(function(index) {
        $(this).children('input.task_position').val(index + 1);
      });
    }
  });  

here's what I have in my _form.html.haml

= f.fields_for :tasks do |t|
  = t.text_field :name
  = t.hidden_field :position, :class => :task_position
  = t.collection_select :account_id, Account.all, :id, :full_name, :prompt => 'Assign task to...'
  .button-group
    %span{:class => "button icon no-text move pill"}
    = t.link_to_remove "", :class => "button icon no-text remove pill"
= f.link_to_add "Add a Task", :tasks, :class => "button icon add"

This worked really well.

Upvotes: 6

Related Questions