Rails 4 datetimepicker and cocoon gem - javascript

Hi have problem with cocoon: https://github.com/nathanvda/cocoon and datetimepicker:http://xdsoft.net/jqplugins/datetimepicker/. When I add through cocoon new nested field my calendar not showing up. I think that I must user cocoon after:insert event in my javascript file but I tried every way and this is not working.
This is my views:
costs.html.haml
= simple_form_for [:partners, #car], url: wizard_path do |f|
= f.simple_fields_for :costs do |cost|
= render 'cost_fields', f: cost
#links
= link_to_add_association '+', f, :costs
= link_to t('cars.back'), previous_wizard_path
= f.submit t('cars.next'), class: 'btn btn-primary'
and my cost_fields partial:
.nested-fields
%table.table.table-striped.table-bordered.dupa
%thead
%th.field
= f.association :cost_type
%th.field
= f.input :netto_price
%th.field
= f.input :document_number
%th.field
= f.association :vat
%th.field
= f.input :type_of_cost
%th.field
= f.input :date, as: :string , :input_html => { :class => 'date' }
= link_to_remove_association "X", f
Any ideas?

As this post eludes, this is because the dynamically added elements are not yet in the DOM.
Try to add a class or id before your nested simple fields (this will already be in the DOM), e.g.:
#container
= f.simple_fields_for :costs do |cost|
= render 'cost_fields', f: cost
Then in your javascript file:
$(document).on('ready page:change', function() {
$('#container').on('cocoon:after-insert', function() {
$('.datetimepicker').datetimepicker();
})
})
Also, I've used this datepicker gem, which allows you to generate a wrapper input/custom date/time fields
= f.input :date, :as => :date_picker

Related

Getting Dropzone.JS to work with Carrierwave and multiple images

I'm fairly new to Rails and I've managed to get multiple uploading to work with carrierwave (after about a week). Now I would like to make the uploading process a bit nicer. I'm not sure what's going on but I can't seem to get it working.
My form looks like this:
.edit-container
= simple_form_for #post, html: { multipart: true } do |f|
.edit-form
= f.input :title
= f.input :location, disabled: true
= f.input :price
= f.input :description
= f.input :contact_number, placeholder: "(999) 999-9999"
= f.label "Category"
= f.text_field :category_name, data: {autocomplete_source: Category.order(:name).map(&:name)}, placeholder: "Choose a category"
= f.fields_for :post_attachments do |p|
= p.file_field :image, :multiple => true, name: "post_attachments[image][]"
= f.button :submit
%script
$('#post_location').val("#{request.location.city}, #{request.location.state}")
I've tried doing this:
.edit-container
= simple_form_for #post, html: { multipart: true, class: "dropzone" } do |f|
.edit-form
= f.input :title
= f.input :location, disabled: true
= f.input :price
= f.input :description
= f.input :contact_number, placeholder: "(999) 999-9999"
= f.label "Category"
= f.text_field :category_name, data: {autocomplete_source: Category.order(:name).map(&:name)}, placeholder: "Choose a category"
= f.fields_for :post_attachments do |p|
= p.file_field :image, :multiple => true, name: "post_attachments[image][]"
= f.button :submit
%script
$('#post_location').val("#{request.location.city}, #{request.location.state}")
And this is the result (obviously NOT what I want):
The error message says:
ActionController::UnknownFormat in PostsController#create ActionController::UnknownFormat
Could you walk me through implementing dropzone.js to my application?

Cocoon Callbacks won't work

I've read through other questions and the cocoon github wiki as well, tried out the sample Rails 4 demo (which works) but I can't get the callbacks to fire on my project.
My gem file is a bit long but the most relevant gems IMHO are cocoon from master (1.2.6), thrubyracer, turbolinks, and spring.
form (note that data-no-turbolinks false and true have had no effect):
%div{"data-no-turbolink" => "false"}
= simple_form_for #course, html: { class: "pure-form"} do |f|
= f.error_notification
.form-inputs
= f.input :name, label: false, placeholder: 'Nombre del Curso', html: {id: 'nombre'}
#subjects.well
= f.input :materia, collection: #materia, prompt: 'Seleccione una materia', value_method: :name
= f.input :tema_de_curso, collection: #tema, prompt: 'Seleccione el tema del curso', value_method: :name
= f.input :grado, collection: #grado, prompt: 'Seleccione el grado', value_method: :name
#bimesters.well
= f.simple_fields_for :bimesters do |bimester|
= render 'bimester_fields', :f => bimester
.links
= link_to_add_association 'Agregar Bimestre', f, :bimesters, class: 'btn btn-primary'
.form-actions
= f.button :submit, class: 'btn btn-success btn-block btn-lg'
partial:
.nested-fields
= f.input :name, collection: #bims, label: 'Bimestre', prompt: 'Seleccione el bimestre', value_method: :name
= link_to_remove_association 'Eliminar Bimestre', f, class: 'btn btn-danger pull-right', style: 'margin-bottom: 1em; '
JS (tried with this extract from the demo project to keep it simple):
$(document).ready(function() {
$('#bimesters').bind('cocoon:before-insert', function(e,task_to_be_added) {
console.log(task_to_be_added);
task_to_be_added.fadeIn('slow');
task_to_be_added.fadeIn('slow');
});
});
Relationship is working correctly as well so models and controller should be fine. I've got the sensation that it might be something to do with turbolinks but all tested permutations have failed.
My main goal is to get the id of the elements that have been created because I'm filtering other nested form partials based on these selections.

How to make a input field visible when a button is clicked or create the same field when a button is clicked for ruby on rails

rails newbie here.
this is my current form
<%= f.input :campaign_name , :input_html => {:style=> 'width: 300px'} %>
<%= f.input :date_range, :input_html => {:style=> 'width: 300px'}%>
<%= f.label :first_event %>
<%= f.collection_select :first_event, eventNames, :to_s, :to_s, include_blank: true %>
<br><br><br>
<%= f.label :second_event %>
<%= f.collection_select :second_event, eventNames, :to_s, :to_s, include_blank: true%>
what i want is this, when user clicks "add filter" i want another field to pop up with the same eventNames array as a collection select.I tried to create another button and get it's tag and if its not the submit button and its add filter button render another form.
but this is terribly bad as a interface and as a user experience.
i want my user to be able to remove the second event field at anytime, without having to submit the form.
So i need to add another button in it to remove the newly made visible form.
How can i achieve this
As i said in my comment if you have a restriction that a user could add only a single or lets say a fixed number of filters then you can simply show and hide your collection by js. Your form would have a hidden collection list
<%= f.input :campaign_name , :input_html => {:style=> 'width: 300px'} %>
<%= f.input :date_range, :input_html => {:style=> 'width: 300px'}%>
<%= f.label :first_event %>
<%= f.collection_select :first_event, eventNames, :to_s, :to_s, include_blank: true %>
<br><br><br>
<%= f.label :second_event %>
<%= f.collection_select :second_event, eventNames, :to_s, :to_s, include_blank: true%>
<%= f.label :third_event, class: "hidden" %>
<%= f.collection_select :third_event, eventNames, :to_s, :to_s, include_blank: true, class: "hidden"%>
hide your collection by css
.hidden{display: none;}
and show it by js when a user click on add filter, assuming it's a link you could do:
= link_to "Add Filter", "#", id: "add-filter"
$(document).on("click","#add-filter", function(e){
$(".hidden").show();
e.preventDefault();
});
If user can add multiple filters then you'll need to add them by ajax. For ajax follow these steps:
a. Create a custom route for your action:
post "/filter" => "your_controller#add_filter", as: "filter"
b. create your link for adding filter:
<%= link_to "Add Filter", filter_path, id: "add-filter", data: {event_id: "2", url: filter_path}%>
c. Get event_id by js and send a ajax request:
$(document).on("click","#add-filter".function(e){
var eventId = $(this).data("eventId");
var url = $(this).data("url");
$.ajax({
type: "POST",
url: url,
data: {id: eventId}
});
})
d. Create add_filter action in your controller:
def add_filter
#event_id = params[:id]
respond_to do |format|
format.js
end
end
e. Create your new collection and append it by js in app/views/your_controller/add_filter.js.erb file
var label = "<%=j label_tag "#{#event_id.humanize}_event" %>"
var collection = "<%=j collection_select(:resource, "#{#event_id.humanize}_event".to_sym , eventNames, :to_s, :to_s, include_blank: true) %>"
$("#form_id").find("select").last().after(label).after(collection);
$("#add-filter").data("eventId","<%=j #event_id + 1 %>");
You'll have to use humanize or number_and_words to convert your #event_id to words format and also you'll have to change :resource accordingly

Rails 3.2 - Ajax call when text field changes

I have a Rails 3.2.13 app with some Ajax on forms and links, using the remote parameter.
The problem is that i can't find in the docs how to do the same with text fields - the
remote parameter didn't work, so i think it's not supported on input objects.
I'd like to do bind 'ajax:xxx' events (like 'ajax:success') on my text_field objects.
I this even possible with UJS? If not, what my options are?
Here's some code:
<%= form_for #post, :html => {:class => 'form-horizontal'} do |f| %>
<div class = 'control-group'>
<%= f.label :title, :html => {:class => 'control-label'} %>
<%= f.text_field :title, :placeholder => 'Title', :class => 'input-xxlarge' %>
</div>
<div class = 'control-group'>
<%= f.label :body, :html => {:class => 'control-label'} %>
<%= f.text_area :body, :placeholder => 'Your post here', :class => 'input-xxlarge',
:rows => 15 %>
</div>
<div class = 'control-group'>
<%= f.label :tags, :html => {:class => 'control-label'} %>
<%= f.text_field :tags, :placeholder => 'Tags separeted by ,', :class => 'input-xxlarge',
:value => '' %>
</div>
<%= f.submit 'Create', :class => 'btn btn-primary'%>
Thanks!
I would bind a change or blur event to the input, and then make the Ajax call manually on your javascript/coffecript file.
posts.js
$('#post_title').change(function() {
// Do your stuff, instantiate variables, etc...
$.ajax({
type: post_or_get,
url: your_url,
data: your_data,
success: function(data) {
// Handle stuff after hitting the server here
},
error: function(data) {
}
});
});

Validation before saving Rails

I would like to carry out a validation before saving by determining if a User has filled in a particular field, the Payment amount field below and chosen status = "Closed" before submitting the form. If he does one without the other then the form should not save
Edit page
<%= simple_form_for #invoice, :html => { :class => 'form-horizontal' } do |f| %>
<%= render "shared/error_messages", :target => #invoice %>
<%= f.association :customer, disabled: #invoice.persisted? %>
<%= f.input :due_date, as: :string, input_html: { class: "datepicker" }, disabled: #invoice.persisted? %>
<%= f.input :invoice_date, as: :string, input_html: { class: "datepicker" }, disabled: #invoice.persisted? %>
<%= f.input :payment_method, as: :select, :collection => [['Cash','Cash'],['Cheque','Cheque'],['In-House transfer','In-House transfer'],['Account Ledger','Account ledger']], :selected => ['Cash','Cash'] %>
<%= f.input :reference_no, :label => 'Payment Reference No', as: :string %>
<%= f.input :amount, as: :string %>
<%= f.input :payment_date, as: :string, input_html: {class: "datepicker"} %>
<%= f.input :status, as: :select, collection: Invoice::VALID_STATUS %>
VALID_STATUS = [ 'Draft', 'Open', 'Closed', 'Void' ] in Invoice.rb
I would like that if the user changes the Status to Closed he should have entered an amount in the form. A user should not be able to change status to closed without entering an amount
In the model (app/models/invoice_model.rb) put
validate :close_must_have_amount
Then define it (same file)
def close_must_have_amount
:status == 'closed' && :amount # May need to tweak this
end
To have the model level validations applied client side you can use
https://github.com/bcardarella/client_side_validations/
1) Javascript Form Validation is generally done by names.
function ValidateForm(){
var form = document.forms['myForm'];
if ((form['status'].value == "Closed") && !(form['amount'].value)){
alert("You gave a 'Closed' status value, but did not provide an amount, please rectify this problem!");
return(false);
} else {
return(true);
}
}
And then:
<%= simple_form_for #invoice, :onsubmit => "ValidateForm();", :html => { :class => 'form-horizontal', :name => 'myForm' } do |f| %>
<%= f.input :amount, :html => { :name => 'amount'}, as: :string %>
<%= f.input :status, as: :select, :html => { :name => 'status'}, collection: Invoice::VALID_STATUS %>
A brief walkthrough onSubmit triggers when a form is submitted, but before it is actually posted to the server.
A javascrtipt function that is trigered by an event and terminates with return(false); will immediately terminate the event, while return(true); (or pretty much anything else really) makes the event continue as planned.
Finally, be aware that relying exclusively on client side validation is a terrible idea, as a determined user could do something like:
1) Make a perfectly legitimate submission with firebug open and inspect the headers etc.
2) Craft their own HTTP request containing bogus/bad data.
3) Submit it through any one of the myriad HTTP tools.
Clientside Validation is a "nice to have".
Serverside Validation is a "must have".
If you want to do it in client side:
<script>
$(document).ready(function(){
$('#status').change(function(){
if($(this).val() == "Closed" && ($('#amount').val() == null || $('#amount') == "")){
alert("Amount must be needed when status is closed")
}
});
});
</script>

Categories

Resources