I have a nested form with checkboxes and text fields. I would like to be able to have the text fields only be enabled if the text box for that specific nested form is clicked/enabled. It is currently hard coded to enable/disable fields if the "custom" text box is set. How can I have javascript update these textbox attributes on the fly?
Form.erb now
<%= simple_nested_form_for #client do |f| %>
<%= f.fields_for :client_prices do |def_price_form| %>
<div class="controls controls-row">
<div class='span10'>
<% if def_price_form.object.custom == true %>
<%= def_price_form.input :custom, :wrapper_html => { :class => 'span1' } %>
<% end %>
<%= def_price_form.input :visit_type, :wrapper_html => { :class => 'span2' } %>
<%= def_price_form.input :price, :wrapper => :prepend, :wrapper_html => { :class => 'span2' }, :label => "Price" do %>
<%= content_tag :span, "$", :class => "add-on" %>
<%= def_price_form.input_field :price %>
<%= def_price_form.link_to_remove '<i class="icon-remove"></i>'.html_safe, :class => 'btn btn-danger', :wrapper_html => { :class => 'span3 pull-left' } %>
<%end%>
<% else %>
<%= def_price_form.input :custom, :hidden => false, :wrapper_html => { :class => 'span1' } %>
<%= def_price_form.input :visit_type, disabled: true, :wrapper_html => { :class => 'span2' } %>
<%= def_price_form.input :price, :wrapper => :prepend, :wrapper_html => { :class => 'span2' }, :label => "Price" do %>
<%= content_tag :span, "$", :class => "add-on" %>
<%= def_price_form.input_field :price, disabled: true %>
<%end%>
<%end%>
</div>
</div>
<% end %>
<%= f.link_to_add "Add a custom price", :client_prices, :class => 'btn btn-success' %>
<p> </p>
<div class="controls">
<%= f.button :submit, :class => 'btn btn-primary' %>
</div>
<% end %>
HTML generated by RoR here
http://jsfiddle.net/59AXJ/
This gets the attribute name from the checkbox that is clicked. Then finds inputs that have similar names, those are the inputs that we will toggle "disabled".
$("input[type='checkbox']").click(function () {
var thisCheckbox = $(this);
var id = $(this).attr("id");
var text = $("label[for=" + id + "]").text().toLowerCase();
var name = $(this).attr("name").replace("[" + text + "]", "");
$("input[name*='" + name + "']").each(function () {
var thisInput = $(this);
if (thisInput.attr("disabled")) {
thisInput.removeAttr("disabled");
} else {
thisInput.attr("disabled", "disabled");
thisCheckbox.removeAttr("disabled");
}
})
});
http://jsfiddle.net/Sbw65/ <-- test it out
As I know, it's impossible to make this on fly, but you can write some unique function on javascript, wich will connect some input with some checkbox by their css class. Something like this (code on CoffeeScript):
changeCheckbox: (class_value) =>
$('[type=checkbox] '+class_value)). on 'check', (e) ->
$input = $(e.currentTarget)
if !$input.prop("checked")
$("input "+class_value).prop('disabled', false)
else
$("input "+class_value).prop('disabled', true)
After that, you just need to add some class for connected checkbox and inputs.
Related
So I have put together a comment section on my rails app from a couple tutorials online. Everything works well, except that when I post a comment, it doesn't get displayed unless I reload the page. I'm using the acts_as_commentable_with_threading gem.
Here's my comments controller:
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
commentable = commentable_type.constantize.find(commentable_id)
#comment = Comment.build_from(commentable, current_user.id, body)
if #comment.save
make_child_comment
redirect_back fallback_location: root_path, :notice => 'Comment was successfully added.'
else
render :action => "new"
end
end
private
def comment_params
params.require(:comment).permit(:body, :commentable_id, :commentable_type, :comment_id)
end
def commentable_type
comment_params[:commentable_type]
end
def commentable_id
comment_params[:commentable_id]
end
def comment_id
comment_params[:comment_id]
end
def body
comment_params[:body]
end
def make_child_comment
return "" if comment_id.blank?
parent_comment = Comment.find comment_id
#comment.move_to_child_of(parent_comment)
end
end
Here are my view files.
_form partial:
.comment-form
= simple_form_for #new_comment, :remote => true do |f|
= f.input :commentable_id, :as => :hidden, :value => #new_comment.commentable_id
= f.input :commentable_type, :as => :hidden, :value => #new_comment.commentable_type
.field.form-group
= f.input :body, :input_html => { :rows => "2" }, :label => false
.field.form-group
= f.button :submit, :class => "btn btn-primary", :disable_with => "Submitting…"
_reply.html.haml
- comments.each do |comment|
.comments-show
.comment
.media.mb-4
.d-flex.mr-3
.float-left.image
- if comment.user.profile_image.present?
.review-img
= image_tag attachment_url(comment.user, :profile_image, :fit, 50, 50, format: "jpg")
- else
%img.review-img{:alt => "user profile image", :src => "https://img.icons8.com/bubbles/100/000000/user.png"}/
.media-body
.small
%b
- if comment.user.username.present?
{comment.user.username}
- else
{comment.user.full_name}
.small.text-muted
{time_ago_in_words(comment.created_at)} ago
.small
{content_tag(:div, comment.body, style: "white-space: pre-wrap;")}
%br
.comment-nav
%a.comment-reply{:href => "#/", class: "btn btn-sm btn-link"} reply
.reply-form
= simple_form_for #new_comment do |f|
= f.hidden_field :commentable_id, value: #new_comment.commentable_id
= f.hidden_field :commentable_type, value: #new_comment.commentable_type
= f.hidden_field :comment_id, value: comment.id
.field.form-group
= f.text_area :body, class: 'form-control'
.field.form-group{:style => "margin-bottom: 60px"}
= submit_tag "Post Reply", class: 'btn btn-primary', style: "float: right;"
%div{:style => "margin-left: 100px;"}
= render partial: "comments/reply", locals: {comments: comment.children}
_template.html.haml
.card.my-2
.scrollable
.card-body
%b
#{pluralize(commentable.comment_threads.count, "Comment")}
%hr
= render :partial => 'comments/form', :locals => { new_comment: new_comment }
= render partial: 'comments/reply', locals: {comments: commentable.root_comments}
comments.js.coffee
$ ->
$('.comment-reply').click ->
$(this).closest('.comment').find('.reply-form').toggle()
return
jQuery ->
$(".comment-form")
.on "ajax:beforeSend", (evt, xhr, settings) ->
$(this).find('textarea')
.addClass('uneditable-input')
.attr('disabled', 'disabled');
.on "ajax:success", (evt, data, status, xhr) ->
$(this).find('textarea')
.removeClass('uneditable-input')
.removeAttr('disabled', 'disabled')
.val('');
$(xhr.responseText).hide().insertAfter($(this)).show('slow')
$(xhr.responseText).hide().insertAfter($(this))
appends a div containing your xhr.responseText with inline style "display: none" after and returns no jquery handle at all.
$(xhr.responseText).hide().insertAfter($(this)).length
> 0
so select the new div as sibling of form element and cast show('slow')
$(this).siblings('div').show('slow')
How do js get the selected value in a dropdown and pass it to the controller so that it returns a list of names for the other dropdown?
What I've done so far:
salmonellas.js
$(function () {
$('body').on('change', "#mode_change", function () {
var selectedText = $(this).find("option:selected").text();
var selectedValue = $(this).val();
if (selectedText) {
$.get('/salmonellas/find_stages?mode_title='+ selectedText, function(selectedText) {
return $(selectedText).html();
});
}
});
});
salmonellas/form.html.erb
<div class="process_salmonellas">
<% f.simple_fields_for :process_salmonellas do |process_salmonella| %>
<%= render 'process_salmonella_fields', :f => process_salmonella %>
<% end %>
</div>
salmonellas/_process_salmonella_fields.html.erb
<div class="mode_change" id="mode_change">
<%= f.collection_select :title, Mode.order(:name), :id, :name, class: 'mode_change', id:'mode_change', include_blank: true, "data-content": :mode_id%>
</div>
<h4>Stage</h4>
<div class="stage">
<% f.simple_fields_for :stages do |stage| %>
<%= render 'stage_fields', :f => stage %>
<% end %>
</div>
salmonella/_stage_fields.html.erb
<div class="form-inputs">
<%= f.grouped_collection_select :title, Mode.order(:name), :steps, :name, :id, :name, class: "step_selection" %>
</div>
salmonellas_controller.rb
def find_stages
#mode = Mode.where("name = ?", params[:mode_title])
#steps = #mode.steps
end
Is looking for another model, why the fields have to be pre-registered. I'm using cocoon to let it nested.
Updating
salmonellas/_process_salmonella_fields.html.erb
<div class="form-inputs">
<%= f.collection_select :title, Mode.order(:name), :id, :name, class: 'mode_change', id:'mode_change', include_blank: true, "data-content": :mode_id%>
</div>
<h4>Stage</h4>
<div class="stage">
<% f.simple_fields_for :stages do |stage| %>
<%= render 'stage_fields', :f => stage %>
<% end %>
</div>
Updating 2
salmonellas/_process_salmonella_fields.html.erb
<div class="form-inputs">
<%= f.collection_select :title, Mode.order(:name), :id, :name, id:'mode_change', include_blank: true %>
</div>
salmonellas.js
$(function () {
$('body').on('change', ".mode_change", function () {
var selectedText = $(this).find("option:selected").text();
var selectedValue = $(this).val();
if (selectedText) {
$.get('/salmonellas/find_stages?mode_title='+ selectedText, function(selectedText) {
return $(selectedText).html();
});
}
});
});
Updating 3
salmonellas.js
$(function () {
$(document).on('change', "#mode_change", function () {
var selectedText = $(this).find("option:selected").text();
var selectedValue = $(this).val();
alert("Selected Text: " + selectedText);
});
});
IDs must be unique on your DOM. You are duplicating them for div and select tag. First change them and use this to get the value of selected option
$(document).on('change', ".mode_change", function () {
var selectedText = $(this).find("option:selected").text();
var selectedValue = $(this).val();
...
I have several checkboxes and have a JQuery function that I want to print out the value I give each checkbox when I click on the checkbox. However, 1 keeps printing out. I assign each checkbox an item.id based on a primary key from my db using Rails. Here is my code
<script>
$(document).ready(function(){
$('input[type="checkbox"]').on("change", function() {
var hall_id = $(this).val(); // here is where I want to get the value that I assigned to the checkbox
if (this.checked) {
console.log( hall_id );
} else {
console.log( hall_id );
}
});
});
</script>
<%= link_to "Logout", root_path %>
<h1>Hello <%= #user.first_name%> <%= #user.last_name%></h1>
<%= form_for #item do |f| %>
<%= f.label :to_do %>:
<%= f.text_field :to_do %><br />
<%= f.hidden_field :email, :value => #user.email%>
<%= f.submit %>
<% end %>
<% #items.each do |item|%>
<%if item.email == #user.email%>
<%= form_for #item do |f| %>
<%= item.id%>
<%= f.check_box :to_do, :value => item.id%> //This is where I assign the value for the check box
<%= item.to_do%><br />
<% end %>
<%end%>
<%end%>
In the image I am trying to print out the number by the checkbox(item.id), but in the console it only prints out 1
Look at the documentation on the check_box helper method: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-check_box
Notice that the optional 4th argument is the checked_value which defaults to 1. Here is how you can switch it to the id of your item object:
<%= f.check_box :to_do, :id, {}, item.id %>
I have the following form in rails:
<%= form_for :key, :url => delete_keys_path,:html => { :method => :get } do |f| %>
<%= f.label :key_value %>
<%= f.text_field :key_value %>
<%= button_to 'Delete', :class => 'btn',
method: :delete,
data: { confirm: 'Are you sure?' } %>
<% end %>
<%= form_for :key ,:url => unblock_keys_path,:html => { :method => :get } do |f| %>
<%= f.hidden_field :key_value %>
<%= button_to 'Unblock', :class => 'btn',
method: :get %>
<% end %>
<%= form_for :key, url: keep_alive_keys_path, :html => { :method => :get } do |f| %>
<%= f.hidden_field :key_value %>
<%= button_to 'Keep Alive', :class => 'btn',
method: :get %>
<% end %>
I want the user to input a key value and choose specific action based on which button he clicks. Since only one input is needed I set up one text field and other hidden fields
The hidden field must be set equal to value in text field on submit. I know i will have to use JavaScript but how do I do it?
Assign an id to the text field, say "textField", and to the hidden field as well, say "hiddenField".
Now using javascript,
var textFieldElement = document.getElementById("textField");
var hiddenFieldElement = document.getElementById("hiddenField");
var text = textFieldElement.value;
hiddenFieldElement.value = text;
I am trying to auto-populate a text field based on the value of another input field. Currently trying to do this using observe_field helper like this:
<%= observe_field(
:account_name,
:function => "alert('Name changed!')",
:on => 'keyup'
) %>
<% form_for(#account, :html => { :id => 'theform' }) do |f| %>
<label for="accountname"> Account name </label>
<%= form.text_field :name, :tabindex => '1' %>
<label for="subdomain"> Subdomain </label>
<%= form.text_field :subdomain, :tabindex => '2' %>
<% end %>
When the user enters text in the account_name text_field, I want to copy that convert into a subdomain (downcase and join by '-') and populate to subdomain text_field.
But, in the process getting this error:
element is null
var method = element.tagName.toLowerCase(); protot...9227640 (line 3588)
Where exactly am I going wrong here? Or is there a better way to do this?
Put your "observe_field" inside the form tag and try again.
EDITED
your observe_field needs to be after the thing it's observing.
Hope that helps :)
For ex:-
<% form_for(#account, :html => { :id => 'theform' }) do |f| %>
<label for="accountname"> Account name </label>
<%= form.text_field :name, :tabindex => '1' %>
<%= observe_field(
:account_name,
:function => "alert('Name changed!')",
:on => 'keyup'
) %>
<label for="subdomain"> Subdomain </label>
<%= form.text_field :subdomain, :tabindex => '2' %>
<% end %>