How to pass id from javascript to rails forms - javascript

I want to pass the selected value from the drop down to fullcalendar plugin and the rails form
The select tag
<%= form_tag appointments_path, :html => {:id => "form-1"} do %>
<%= select_tag(:worker_id, options_from_collection_for_select(#client.workers, :id, :name), :selected => #a, :style=>"width:170px;", :prompt => "Select Staff Member")%>
<% end %>
I am passing the #a variable by ajax to
<script>
$('#worker_id').change(function (e) {
var a = parseInt($(this).val());
alert(a);
$.ajax({
type: "GET",
url:"/customers/new",
data : { id: a },
success:function(result){
$('#content1').html("<%= escape_javascript(render :partial =>'form', :locals => ????) %>");
}
});
$('#calendar').fullCalendar('destroy');
RenderCalendar($(this).val());
});
</script>
I am not sure whether i am doing it in right way. I want to pass the value in form which is here:
<%= form_for(#customer) do |f| %>
<%#= f.error_notification %>
<div class="field">
<%#= f.label :Service_Name %>
<%#= f.collection_select :service_id, Category.where(:client_id => #client).order(:name), :services, :name, :id, :service_name %>
</div>
<br /> <br />
<%= f.fields_for :appointments do |builder|%>
<fieldset>
<% if #a!=0 %>
<%= builder.hidden_field :worker_id, :value=> #customer.worker_id %>
<%= builder.hidden_field :client_id, :value=> #client.id%>
<%= builder.label :price %>
<%= builder.text_field :price %>
<%= builder.label :Service_Name %>
<%= builder.collection_select(:service_id, #a.order(:service_name), :id, :service_name, :include_blank => true, :multiple => true ) %>
<% end %>
<%= builder.label :appointment_date %>
<%= builder.date_select :appointment_date %> <br />
<%= builder.label :appointment_start_time %>
<%= builder.time_select :appointment_start_time, ampm: true %> <br />
<%= builder.label :appointment_end_time %>
<%= builder.time_select :appointment_end_time, ampm: true %>
</fieldset>
<%end%>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.hidden_field :worker_id, :value=>#customer.worker_id %>
</div>
<div class="form-actions">
<%= f.button :submit, :class=>"btn btn-primary" %>
</div>
<% end %>

If I understand correctly: you are trying to rerender the fullcalender jquery plugin with your ajax success callback based on the user selected from the select tag here:
<%= form_tag appointments_path, :html => {:id => "form-1"} do %>
<%= select_tag(:worker_id, options_from_collection_for_select(#client.workers, :id, :name), :selected => #a, :style=>"width:170px;", :prompt => "Select Staff Member") %>
<% end %>
There is an inherent issue with the way you're trying to do this. Any embedded ruby in your views will run only once at runtime. Essentially, your escape_javascript(render partial..... will not run because any embedded ruby is done running at that point.
What you could do is keep the ajax call you already have but run the render partial code in your '/customers/new', instead of trying to call it in the ajax callback -which is after runtime
render :partial =>'form', :locals => ????
This will return the partial code with which you want to then place on the page. With your ajax, simply place it on the page something like this:
success:function(result){
$('#content1').html(result);
}

Related

Make form field required if other form field is set

I am trying to have the POC field be a required field if the location is set to Deployed, but not if it is set to Local. I tried this below:
<%= form_with(model: hardware, local: true, multipart: true) do |form| %>
<% if hardware.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(hardware.errors.count, "error") %> prohibited this hardware from being saved:</h2>
<ul>
<% hardware.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label "Location" %>
<%= form.select :location, ['Local', 'Deployed'] %>
</div>
<div class="field">
<%= form.label "POC" %>
<% if (:location == 'Deployed')%>
<%= form.collection_select(:poc_id, Poc.all, :id, :name, { :prompt => 'Select a POC', :selected => #hardware.poc_id, include_blank: true }, { class: 'form-control', required: true }) %>
<% else %>
<%= form.collection_select(:poc_id, Poc.all, :id, :name, { :prompt => 'Select a POC', :selected => #hardware.poc_id, include_blank: true }, { class: 'form-control' }) %>
<% end %>
</div>
When I run it like this, it does not give any errors, but does not require the field. The only difference between the two collection selects is at the end where I set the required: true flag for the if statement and have it off on the else statement.
Is there a way to do this with the method I am trying? Are there any Ruby Form Helpers that will allow the feature? Do I need to use Javascript to implement this feature?

Rails 3 Nested Model Form with Javascript

I have created a nested model form for Lessons to Questions and Answers. It was not picking up the coffee script so I have add it the coffee code as Javascript but i am get an error and Add Question is not working. Anyone and assist please.
Lesson.rb
has_many :questions
accepts_nested_attributes_for :questions, :allow_destroy => true
Question.rb
belongs_to :lesson
has_many :answers
accepts_nested_attributes_for :answers, :allow_destroy => true
Answer.rb
belongs_to :question
application_helper.rb
def link_to_add_fields(name, f, association) new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, :child_index => id) do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to(name, '#', :class => "add_fields", :data => {:id => id, :fields => fields.gsub("\n", "")}) end
admin/lessons/_form.html.erb
<%= form_for([:admin,#lesson]) do |f| %>
<% if #lesson.errors.any? %>
<div class="notification error png_bg">
<img src="/assets/admin/icons/cross_grey_small.png" title="Close this notification" alt="close" />
<div>
<h2><%= pluralize(#lesson.errors.count, "error") %></h2>
<ul>
<% #lesson.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
<label class="formlabel">Lesson Title</label>
<%= f.text_field :title %>
<%= f.fields_for :questions do |builder| %>
<%= render 'question_fields', :f => builder %>
<% end %>
<%= link_to_add_fields "Add Question", f, :questions %>
<%= f.submit 'Save', :class => 'button' %>
_question_fields.html.erb
<fieldset>
<%= f.label :content, "Question" %><br />
<%= f.text_area :content %><br />
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Question" %>
<%= f.fields_for :answers do |builder| %>
<%= render 'answer_fields', :f => builder %>
<% end %>
<%= link_to_add_fields "Add Answer", f, :answers %>
</fieldset>
_answer_fields.html.erb
<fieldset>
<%= f.label :content, "Answer" %>
<%= f.text_field :content %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Answer" %>
</fieldset>
Here is the javascript I have added just before the end of the the head tag. I am getting an error of "$('form').on is not a function. (In '$('form').on', '$('form'....
<script>
jQuery(function() {
$('form').on('click', '.remove_fields', function(event) {
$(this).prev('input[type=hidden]').val('1');
$(this).closest('fieldset').hide();
return event.preventDefault();
});
return $('form').on('click', '.add_fields', function(event) {
var regexp, time;
time = new Date().getTime();
regexp = new RegExp($(this).data('id'), 'g');
$(this).before($(this).data('fields').replace(regexp, time));
return event.preventDefault();
});
});
</script>
Jquery .on() function needs at least jquery 1.7 to work. Update your jquery or use .bind() in place of .on().

How to Create Nested Forms in Rails 4

I'm trying to let a user create Exercises with Equipment and Muscles in many-to-many relationships through their respective join tables( exercise_equipment, exercise_muscles ). I've gotten the form working for adding one equipment/muscle per exercise, but cannot figure out how to add a link to add another field to the form on the fly.
I've checked out RailsCasts, this post, have asked it as a side question on a previous post of my own, but simply cannot get this functionality to work. I'm fairly new to Rails 4 and am still trying to learn Javascript, but I'd love a thorough explanation of how to set this up the Rails 4 way!
My Models:
# id :integer
# name :string
# is_public :boolean
Exercise
has_many :exercise_equipment
has_many :equipment, :through => :exercise_equipment
accepts_nested_attributes_for :exercise_equipment
# id :integer
# exercise_id :integer
# equipment_id :integer
# optional :boolean
ExerciseEquipment
belongs_to :exercise
belongs_to :equipment
accepts_nested_attributes_for :equipment
# id :integer
# name :string
Equipment
has_many :exercise_equipment
has_many :exercises, :through => :exercise_equipment
My Controller Methods:
def new
#exercise = Exercise.new
#exercise.exercise_equipment.build
#exercise.exercise_muscles.build
end
def create
exercise = current_user.exercises.new( exercise_params )
if exercise.save!
redirect_to exercise
else
render 'new'
end
end
views/exercises/new.html.erb
<h1>Create New Exercise</h1>
<%= form_for #exercise do |f| %>
<%= render 'form', f: f %>
<%= f.submit "New Exercise" %>
<% end %>
views/exercises/_form.html.erb
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true %>
<%= f.check_box :is_public %> Public
<%= f.fields_for :exercise_muscles do |emf| %>
<%= emf.collection_select :muscle_id, Muscle.all, :id, :name, { include_hidden: false } %>
<% end %>
<%= f.fields_for :exercise_equipment do |eef| %>
<%= eef.collection_select :equipment_id, Equipment.all, :id, :name, { include_hidden: false } %>
<%= eef.check_box :optional %> Optional
<% end %>
Ajax
Cannot figure out how to add a link to add another field to the form
on the fly
The "Rails way" of doing that is to "pull" a new instance of the fields_for block from an ajax request.
The reason why Ajax is recommended is because it's the "Rails way" to do it - completely modular & extensible:
#config/routes.rb
resources :exercises do
get :add_field, on: :collection
end
#app/models/exercise.rb
Class Exercise < ActiveRecord::Base
...
def self.build #-> allows you to call a single method
exercise = self.new
exercise.exercise_equipment.build
exercise.exercise_muscles.build
return
end
end
#app/controllers/exercises_controller.rb
Class ExercisesController < ApplicationController
def add_field
#exercise = Exercise.build
respond_to do |format|
format.html
format.js
end
end
end
#app/views/exercises/new.html.erb
<%= form_for #exercise do |f| %>
<%= render "fields", locals: { f: f } %>
<%= f.submit %>
<% end %>
#app/views/exercises/add_field.js.erb
$("#form_element").append("<%=j render "exercises/form", locals: { exercise: #exercise } %>");
#app/views/exercises/_form.html.erb
<%= form_for exercise do |f| %>
<%= render "fields", locals: { f: f } %>
<% end %>
#app/views/exercises/_fields.html.erb
<%= f.fields_for :exercise_muscles, child_index: Time.now.to_i do |emf| %>
<%= emf.collection_select :muscle_id, Muscle.all, :id, :name, { include_hidden: false } %>
<% end %>
<%= link_to "New Field", exercises_add_fields_path, remote: :true %>
<%= f.fields_for :exercise_equipment, child_index: Time.now.to_i do |eef| %>
<%= eef.collection_select :equipment_id, Equipment.all, :id, :name, { include_hidden: false } %>
<%= eef.check_box :optional %> Optional
<% end %>
<%= link_to "New Field", exercises_add_fields_path, remote: :true %>
This will give you the ability to create the fields through an ajax call; which is the correct way to do it
After attempting to use Rich's solution, I wanted to find one that was a bit more minimal in terms of the code used. I found the gem Cocoon, which works great and was very simple to integrate.
My main _form view:
<div class="form-group">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true %>
</div>
<div class="form-group">
<%= f.check_box :is_public %> Public
</div>
<div class="form-group">
<%= f.fields_for :exercise_muscles do |emf| %>
<%= render 'exercise_muscle_fields', :f => emf %>
<% end %>
<%= link_to_add_association 'Add Muscle', f, :exercise_muscles %>
</div>
<div class="form-group">
<%= f.fields_for :exercise_equipment do |eef| %>
<%= render 'exercise_equipment_fields', :f => eef %>
<% end %>
<%= link_to_add_association 'Add Equipment', f, :exercise_equipment %>
</div>
As can be seen here, the addition of a simple "link_to_add_association" method takes care of all of the Javascript in the background. For future readers, here are the partials that each of these form-groups contain:
_exercise_muscle_fields:
<%= f.collection_select :muscle_id, Muscle.all.order( 'muscle_group_id ASC' ), :id, :name, { include_hidden: false } %>
_exercise_equipment_fields:
<%= f.collection_select :equipment_id, Equipment.all.order( 'name ASC' ), :id, :name, { include_hidden: false } %>
<%= f.check_box :optional %> Optional

Undefined form variable when rendering a partial in rails after an AJAX call

I have been trying for a while to implement a dynamic dependent form using AJAX in rails 4.0. I have a bike model which has_one make and model. It also has_many quotes. The goal is to have the second form's collection field (model) populate after the first field make is selected.
The form loads correctly and the AJAX call once the first field is selected is made and returns the appropriate set of data (confirmed via puts in the console). However, I am unable to figure out how to then render the partial appropriately. I am getting the error below. I understand there is no f variable once the partial is rendered via the AJAX call but how do I go about designing the form without the f variable?
ActionView::Template::Error (undefined local variable or method `f' for #<#<Class:0x007f95b0fc2068>:0x007f95b54e2490>):
1: <%= f.label :name, 'Model' %>
2: <% if !current_models.blank? %>
3: <%= f.collection_select :name, current_models.collect{ |m| [m.name,m.id]}, :id , :name, include_blank: true %>
4: <% else %>
app/views/shared/_model_questions_fields.html.erb:1:in `_app_views_shared__model_questions_fields_html_erb__894239665582553972_70140482609500'
app/controllers/quotes_controller.rb:70:in `update_model_select'
quotes/new.html.erb
<%= form_for #quote do |f| %>
<%= f.fields_for :bikes do |builder| %>
<p><%= render 'shared/bike_questions_fields', :f => builder %></p>
<% end %>
<%= f.submit "Show Quote", class: "btn btn-large btn-primary" %>
<% end %>
'shared/bike_questions_fields'
<%= f.fields_for :makes do |builder| %>
<p><%= render 'shared/make_questions_fields', :f => builder %></p>
<% end %>
<%= f.fields_for :models do |builder| %>
<div id="bikeModels"
<p><%= render 'shared/model_questions_fields', :f => builder, :current_models => [] %></p>
</div>
<% end %>
'shared/model_questions_fields'
<%= f.label :name, 'Model' %>
<% if !current_models.blank? %>
<%= f.collection_select :name, current_models.collect{ |m| [m.name,m.id]}, :id , :name, include_blank: true %>
<% else %>
<%= f.collection_select :name, [], :id , :name, include_blank: true %>
<% end %>
in quotes controller:
def update_model_select
models = Model.where(:make_id=>params[:id]).order(:name) unless params[:id].blank?
render :partial => "shared/model_questions_fields", :locals => { :current_models => models }
end
in quotes.js.coffee:
ready = ->
jQuery ($) ->
# when the #make field changes
$("#quote_bikes_makes_name").change ->
# make a POST call and replace the content
make = $("select#quote_bikes_makes_name :selected").val()
make = "0" if make is ""
jQuery.get "/quotes/update_model_select/" + make, (data) ->
$("#bikeModels").html data
false
$(document).ready(ready)
$(document).on('page:load', ready)
I solved this by changing 'shared/model_questions_fields' to:
<%= form_for('quote', remote: true) do |f| %>
<%= f.fields_for :bikes do |g| %>
<%= g.fields_for :models do |i| %>
<%= i.label :name, 'Model' %>
<% if !current_models.blank? %>
<%= i.collection_select :name, current_models, :id , :name, include_blank: true %>
<% else %>
<%= i.collection_select :name, [], :id , :name, include_blank: true %>
<% end %>
<% end %>
<% end %>
<% end %>

Ruby on Rails and onchange

I got this code for a small calculator:
<%= form_tag calculators_path, :method => :post, :remote => true do %>
<%= text_field_tag :data %> = <span id="sum"></div>
<% end %>
Can someone tell me how i can add the JS/Ajax onchange command to it, so the calculator automatically shows the result?
Sorry for that newbish question, im a total beginner.
:)
<%= form_tag calculators_path, :method => :post, :remote => true do %>
<%= text_field_tag :data, nil, :onkeyup => "this.form.sub.click()" %> = <span id="sum"></span>
<%= submit_tag "ok", :name => "sub" %>
<% end %>

Categories