I have the following code to create a nested model (invoice_line_items) within my invoice model:
= nested_form_for #invoice, mutipart: true, class: "form-horizontal" do |f|
...
%table.table.table-bordered{:id => "line-items"}
%thead
%tr
%th
%th Description
%th Quantity
%th Rate
%tbody
%tr
= f.fields_for :invoice_line_items do |line_item|
%td= line_item.link_to_remove "X"
%td= line_item.text_field :description
%td= line_item.text_field :quantity, :class => "input-mini"
%td= line_item.text_field :rate, :class => "input-mini"
= f.link_to_add "Add", :invoice_line_items, :data => { :target => "#line-items" }
I have two problems: 1) when I add a new row by clicking "Add"....it doesn't match the table formatting and doesn't insert into the table. I tried everything to get it to work and it just doesn't. I also tried adding the ":target" as mentioned by ryanb in his gem docs. 2) I would like to have 3 invoice_line_items initially ready for the user on the invoice page, but i'm not sure how to do that.
EDIT: I got something a little different now since I've been playing around with it. I don't think i'm doing it right still but now it creates a new form each time I click "add":
.row-fluid
= f.fields_for :invoice_line_items, :wrapper => false do |line_item|
%table.table.table-bordered#tasks
%thead
%th
%th Description
%th Quantity
%th Rate
%tr.fields
%td= line_item.link_to_remove "X"
%td= line_item.text_field :description
%td= line_item.text_field :quantity, :class => "input-mini"
%td= line_item.text_field :rate, :class => "input-mini"
.row-fluid
= f.link_to_add "Add", :invoice_line_items, :data => { :target => "#tasks" }
This was a tough one to figure out but it turns out that the most updated version of the nested_form gem doesn't come with the most recent version of the jquery_nested_form.js file (even though the documentation says to use this function). So, to get this to work, I had to add this to my application.js:
$(function ($) {
window.NestedFormEvents.prototype.insertFields = function(content, assoc, link) {
var target = $(link).data('target');
if (target) {
return $(content).appendTo($(target));
} else {
return $(content).insertBefore(link);
}
};
});
this overwrote the function in jquery_nested_form.js and now everything works.
Related
I'm using the cocoon gem in my rails project, and I have two "link_to_add_association", but I need that depending on which link_to is pressed to do a certain function, link_to with id "link_1" adds the records to the beginning of the table and the other one adds the records at the end with other values, this is my partial form:
= form_for([#billing, #payment]) do |f|
- if #payment.errors.any?
= render partial: 'layouts/partials/errors/form_errors', locals: { errors: #payment.errors }
= f.hidden_field :billing_id, value: #billing.id
.row
.col-md-6
.form-group.row
.col-md-4
= f.label :payment, class: 'form-control-label'
.col-md-8
= f.text_field :payment, class: 'form-control text-right', 'data-currency-format--live': '', 'data-target': '#total-pay'
.col-md-6
.form-group.row
.col-md-4
= f.label :day, class: 'form-control-label'
.col-md-6
= f.text_field :day, class: 'form-control datepicker', 'data-startView': 'days', 'data-minyear': #billing.date_bill.year, 'data-minmonth': #billing.date_bill.month, 'data-minday': #billing.date_bill.day
.col-md-1
.links
= link_to_add_association 'add', f, :payment_details, partial: 'payment_detail_fields',:"data-association-insertion-node" => "tbody.details",:"data-association-insertion-method" => "prepend", class:"btn btn-success btn-xs", id: "link_1"
.col-md-1
.links
= link_to_add_association 'add', f, :payment_details, partial: 'payment_detail_discount_fields',:"data-association-insertion-node" => "tbody.details",:"data-association-insertion-method" => "append", class:"btn btn-success btn-xs", id: "link_2"
.col-md-12
#payment_details
%table.tabla_personalizada
%thead
%tr
%th value_paid
%th voucher
%th accion
%th value_paid
%th value_paid
%th voucher
%th accion
%tbody.details
= f.fields_for :payment_details do |payment_detail|
= render 'payment_detail_fields', f: payment_detail
%tr
%td
%td
%td
%td
%td
%td
%td
%tr.descuentos
%td Descuento
%td Descuento
%td
%td
%td
%td
%td
.row
.col-md-12
= f.label :comments, class: 'form-control-label'
= f.text_area :comments, class: 'form-control', rows: 6
%hr
.row
.col-md-8
.form-group.row
.col-md-8
= f.submit :class => 'btn btn-primary'
- content_for :javascript do
:javascript
$(document).ready(function() {
$("#link_1").on("cocoon:after-insert", function() {
alert("element of link_1");
} )
$("#link_2").on("cocoon:after-insert", function() {
alert("element of link_2");
} )
});
I tried this code but I can't find a way to make it work
$(document).ready(function() {
$("#link_1").on("cocoon:after-insert", function() {
alert("element of link_1");
} )
$("#link_2").on("cocoon:after-insert", function() {
alert("element of link_1");
} )
});
I'm pretty new in Rails and I need your help.
I have Job model, Invoice model and Item model.
job.rb model have - has_one :invoice, dependent: :destroy accepts_nested_attributes_for :invoice
invoice.rb have - belongs_to :job, optional: true, :foreign_key => 'job_id' has_many :items, dependent: :destroy accepts_nested_attributes_for :items
item.rb have - belongs_to :invoice, optional: true, :foreign_key => 'invoice_id'
Everything is ok, it creating the job and invoice with items inside and on invoice show it generate the invoice but in invoices/index I want to list all invoices in a table but I can't get = #invoice.job.customer_name.capitalize it give me a error - NoMethodError in Invoices#index undefined method `customer_name' for nil:NilClass.
It is like job is nil. My question is why in invoices/show.html.erb I can access
= #invoice.job.customer_name.capitalize and in index it give me error ?
As you can see in invoices/show.html.haml I have = #invoice.job.customer_name.capitalize and it give me correct data:
.container.invoice
.row
.col-sm-6
- if current_user.logo.present?
= image_tag current_user.logo.url(:thumb)
- else
= image_tag 'blank.jpg'
.col-sm-3
.col-sm-3
%h3
= current_user.full_name.titleize
%p
= current_user.email
%p
= current_user.phone
%hr
.row
.col-sm-6
%h4
Customer :
= #invoice.job.customer_name.capitalize.html_safe
%p
%b
Phone:
= #invoice.job.customer_tel
%p
%b
Email:
= #invoice.job.customer_email
.col-sm-3
.col-sm-3
%p
%b
Invoice: #
= #invoice.id
%p
%b
Date:
= #invoice.created_at.strftime("%B %d, %Y")
%hr
.row
.col-sm-12
%table.table.table-striped.table-hover
%thead
%tr.sortable-table
%th.col-sm-1
Item Id
%th.col-sm-3
Item/Operation
%th.col-sm-3
Unit cost/Hr rate
%th.col-sm-3
Qty
%th.col-sm-2
%th.col-sm-3
Amount
%tbody
- #invoice.items.each do |item|
%tr.sortable-table
%th
= item.id
%th
= item.name
%th
= number_to_currency item.unit_cost
%th
= item.qty
%th
%th
- amount = number_to_currency(item.unit_cost * item.qty)
= amount
%hr
.row
.col-sm-6
.col-sm-3
.col-sm-3
%b
Subtotal
- sum = 0
- #invoice.items.each do |item|
- if item.qty?
- subtotal = (item.unit_cost * item.qty)
- sum += subtotal
= number_to_currency(sum)
%p
%b
Tax
= number_to_currency(sum * (#invoice.tax/100))
%p
%h4
%b
Total
= number_to_currency((sum * (#invoice.tax/100)) + sum)
%hr
= link_to 'Edit', edit_invoice_path(#invoice)
\|
= link_to 'Back', invoices_path
But in invoices/_invoice.html.erb I have the error :
%h1 Listing invoices
%table.table.table-striped.table-hover
%thead
%tr.sortable-table
%th
Id
%th
Job Id
%th
Item
%th
Unit cost
%th
Qty
%th
Amount
%tbody
= render #invoices
%br
= link_to 'New Invoice', new_invoice_path
<tr>
<td>
<%= invoice.id %>
</td>
<td>
<%= invoice.job_id %>
</td>
<td>
</td>
<td>
<%= invoice.unit_cost %>
</td>
<td>
<%= invoice.qty %>
</td>
<td>
<%= invoice.job.customer_name %>
</td>
<td>
<%= link_to 'Details', invoice, class: 'btn btn-primary btn-xs' %>
</td>
<td>
<%= link_to "", edit_invoice_path(invoice), id: "edit_#{invoice.id}", class: 'glyphicon glyphicon-pencil index-icons' %>
</td>
<td>
<%= link_to "", invoice_path(invoice), method: :delete, id: "delete_invoice_#{invoice.id}_from_index", class: 'glyphicon glyphicon-trash index-icons', data: {confirm: 'Are you sure ?'} %>
</td>
</tr>
Thank you, and if you need more code let me know.
Update:
[you see invoice Id 47 have job id 67][1]
[the job id 67 is exist][2]
[on the invoice show I have name of customer][3]
[1]: https://i.stack.imgur.com/ODAkb.png
[2]: https://i.stack.imgur.com/uGK21.png
[3]: https://i.stack.imgur.com/sRTWS.png
NoMethodError in Invoices#index undefined method `customer_name' for
nil:NilClass.
This means where you are calling customer_name:
#invoice.job.customer_name.capitalize.html_safe
You are calling it on nil, or in other words:
#invoice.job
returns nil. If the invoice does not have a job associated with it, any methods involving the invoice's job will fail (apart from just #invoice.job, which will return nil).
Your two options are to either make sure every invoice has a job associated with it before rendering, or to rewrite your view template as:
.container.invoice
.row
.col-sm-6
- if current_user.logo.present?
= image_tag current_user.logo.url(:thumb)
- else
= image_tag 'blank.jpg'
.col-sm-3
.col-sm-3
%h3
= current_user.full_name.titleize
%p
= current_user.email
%p
= current_user.phone
%hr
.row
.col-sm-6
- if #invoice.job
%h4
Customer :
= #invoice.job.customer_name.capitalize.html_safe
%p
%b
Phone:
= #invoice.job.customer_tel
%p
%b
Email:
= #invoice.job.customer_email
.col-sm-3
.col-sm-3
%p
%b
Invoice: #
= #invoice.id
%p
%b
This will only display the bottom section of the view if a job is associated with the #invoice
index.html.haml
I have a customer details form which has a nested form named 'goods address'. I want to display all the customer details in index page.
%tbody
- #customer_details.each do |customer|
%tr
%td= customer.customer_name
%td= customer.customer_id
%td= customer.address
%td= customer.state
%td= customer.email
nested form
= fields_for customer_detail do |f|
= f.fields_for :goods_address do |t|
.fieldset
.row
.col-sm-12
= t.label :delivery_address,"Goods to be delivered at same address mention above?", class: "col-sm-6 control-label text-right"
= t.check_box :delivery_address, autofocus: true, class: "toggle-two customer-goods col-sm-6", :value => "On"
%br
%div{id: 'customer_goods'}
.main-center-pan.main-login-pan
.fieldset
.row
.col-sm-12
= t.label :name,"Name", class: "col-sm-3 control-label text-right"
= t.text_field :name, autofocus: true, class: "col-sm-3"
= t.label :contact_no,"Contact number", class: "col-sm-3 control-label text-right"
= t.text_field :contact_no, autofocus: true, class: "col-sm-3"
%br
parent form
= nested_form_for(#customer_detail) do |f|
- all_views_side_error_messages!(#customer_detail)
.form-alignment
.fieldset
.row
.col-sm-12
= f.label :customer_name,"Organisation/Customer Name", class: "col-sm-3 control-label text-right"
= f.text_field :customer_name, autofocus: true, class: "col-sm-3"
= f.label :residential_type,"Residential Type", class: "col-sm-3 control-label text-right"
= f.check_box :residential_type, autofocus: true, "data-width" => "200", class: "toggle-two-resident select-resident col-sm-3"
%br
The problem is I dont know how to define the nested form's fields in the index.can someone plz help me.Thanks in advance.
If you want to display the child-attributes(goods_address) with parent(customer_details), just loop the association of the parent object.
%tbody
- #customer_details.each do |customer|
%tr
%td= customer.customer_name
%td= customer.customer_id
%td= customer.address
%td= customer.state
%td= customer.email
- if customer.goods_address.present?
%td= customer.try(:goods_address).try(:delivery_address)
%td= customer.try(:goods_address).try(:name)
%td= customer.try(:goods_address).try(:contact_no)
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!
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.
I am creating an equipment and I have two actions in my equipment controller, new and create.. and I have two views which is new and a partial form..
I also have four tables.. which are equipments, equipment_types, equipment_locations, and equipment_management_informations..
The form looks like..
>= error_messages_for 'equipment'
%table.contentText{:style => "width: 100%"}
- if #types
%tr
%td Equipment Type
%td= collection_select 'equipment', 'equipment_type_id', #types, :id, :name, {}, :class => "dropdownSelect"
%tr
%td Location
%td= select 'equipment', 'equipment_location_id', #equipment_locations.collect { |e| ["#{e.name.capitalize!}", e.id]},{}, :class => "dropdownSelect"
%tr
%td Serial Number
%td= text_field 'equipment', 'serial_number', :class => 'textFields'
%tr
%td MAC Address
%td= text_field 'equipment', 'mac_address', :class => 'textFields'
%tr
%td IP Address
%td= text_field 'equipment', 'ip_address', :class => 'textFields'
- if #stands
%tr
%td Stand
%td= collection_select 'equipment', 'stand_id', #stands, :id, :street_no, :include_blank => true
%tr
%td{:valign => 'top'} Description
%td= text_area 'equipment', 'description', :cols => 45, :rows => '3', :class => "txt_area_effect"
and my new view is like:
> %h3 New equipment
%div{:style => "border: 1px solid #CCC;"}
- form_tag :action => 'create', :estate_id => #estate do
= render :partial => 'form'
= submit_tag "Create"
- action = "list"
%input{:type => "button", :value => "Back", :onclick => "window.location='#{action}';", :class => "start"}
and my create action display this a nil when i inspect it
#equipment = Equipment.find(params[:equipment])
it gives an error like
Unknown key(s): equipment_type_id, mac_address, description, equipment_location_id, serial_number, ip_address
#equipment = Equipment.find(params[:equipment])
should be:
#equipment = Equipment.new(params[:equipment])
or
#equipment = Equipment.new(params[:equipment])
(just posting answer from comments so this stops showing as unanswered)