I am trying to write a rails application which lets you go to a certain page, say /person/:id. On this page it shows a set of available resources. I want each resource to have a button next to it, which reserves that resource to that person (by creating a new instance of an Allocation model.) As an extension, I'd like several buttons by each resource, that cancel reservations and do other things. I'd also like to input data alongside some of the buttons, e.g. to allocate some % of a resource.
My problem is I can't work out how to sensibly do this without repeating myself, or having a very hacky controller. How can I do this without matching on the value part of the submit buttons (the text on the buttons), or using any javascript?
Additionally, if you have two forms on a page, how do you set it up so changes on both forms are saved when any submit button is clicked?
im using jQuery, and this is what i did :
<script type="text/javascript">
$(document).ready(function() {
$('#bulk_print').click(function(){
var target = '<%= bulk_print_prepaid_vouchers_path(:format => :pdf) %>';
$('#prepaidvoucher_bulk_print').attr('action', target);
$('#prepaidvoucher_bulk_print').submit();
});
$('#bulk_destroy').click(function(){
var target = '<%= bulk_destroy_prepaid_vouchers_path %>';
$('#prepaidvoucher_bulk_print').attr('action', target);
$('#prepaidvoucher_bulk_print').submit();
});
});
</script>
<% form_tag '#', :method => :post, :id => 'prepaidvoucher_bulk_print' do %>
your form details
<button class="button" type="submit" id="bulk_print">
<%= image_tag("web-app-theme/printer.png", :alt => "Print Selected Vouchers") %> Print Selected Vouchers
</button>
<button class="button" type="submit" id="bulk_destroy">
<%= image_tag("web-app-theme/cross.png", :alt => "Delete Selected Vouchers") %> Delete Selected Vouchers
</button>
<% end %>
The idea is to change the form action on the fly, based on which button is clicked
Make each row in the list a form and put the info about the item in question there. Of course, you'll need to submit and reload the page with each action. The only way around this is to use checkboxes instead of buttons and make it one big form — or to use Javascript.
As for your second question, if you want to have a submit button affect two "forms," you should make them both part of the same form. You can have multiple submit buttons on the form if you need to. Otherwise, you could dynamically generate a third form with Javascript filled with the values from the original form — but that wouldn't work in all cases (e.g., file inputs).
Related
Edited:
I am trying to achieve cascading dropdown.
In my 1st dropdown, I get all the distinct Names.
<%= f.input :names, collection: names.distinctnames, :label => "Select Name" %>
On selecting the name, how to access the value and pass it to controller/model so that I can filter based on the values and bind it to the next dropdown.
In my Model, I have the following scope
scope :distinctnames, ->{ Names.distinct.pluck(:names)}
Here, I want to add another scope that gives the cities for the selected name.
So, how would I get the data selected in my view and get all the values in the next dropdown.
If this is the wrong approach, can someone suggest me the alternative one with and example.
My code
<!DOCTYPE html>
<html>
<head>
<script>
$(document).on('change', '#names_id', function(){
var custId = $(this).val();
return custId;
});
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-6 col-lg-offset-3">
<div class="panel panel-primary">
<div class="panle-heading">Panel Primary</div>
<div class="panel-body">
<%= simple_form_for #ruby, url:{action: 'create'}, html: {class: 'form'} do |f| %>
<%= f.select :names_id, options_for_select(Names.distinctnames), {}, {:multiple => true} %>
<%= f.select :city_name, options_for_select(Names.where(names_id: custId).pluck(:city_name)), {}, {:multiple => true} %>
<% end %>
</div>
</div>
</div>
</div>
<div>
</body>
</html>
Here, at the time of loading the the view I get undefined local variable or method `custId' for #<#
How to load the all other dropdowns empty and then bind the value from the selected dropdown value to the second one.
So as I understand, You got more than one drop down list but the got dependency, Like selected value from drop-down list 1 will affect values in drop-down list 2, In this case reaching the controller action will need the form to be submitted, If what I'm thinking about is right I have more than one idea:
First one
You will use javascript or JQuery library to add this dynamic behavior to you page, the scenario is going to be like this:
1- User will select value
2- an actionListner is fired using js when select.
3- send a request to the server
4- get data according to parameters you sent to the server
5- enable the next drop-down list after binding returned data from the server.
This solution won't need you to refresh the page, Which I think will make user satisfied.
Second solution
You will put actionListner on drop-down and submit the form when user select value.
This gonna need a little bit validation in you server-side plus a little bit effort to save data that was filled if there is other inputs(saving them in instance variables I mean like #select_drop_1 and use them in inputs as user gonna feel that values are not missed).
Third solution
If it is applicable that you make this data available once user opened the form, By this I mean grouping this data, Making a query that groups cities by these distinct names, So that when user select a name, a simple js code will run enabling and binding data to the next drop-down and so on.
If I were you I would choose either first or third option, Pardon me because I don't know the schema of your application, I don't know if it is applicable to make grouping I'm imagining that Names got its table and there is another one called City.
Hope it helps.
The problem I'm running into deals with rendering a partial. I basically have a link which should get updated after the user puts some text in a text field. The first time it works fine. The user types in the text, the link gets updated and then when the link is clicked the partial is rendered with the correct information. However when the text is changed the link also gets update with the new parameters to pass to the action but when the link is clicked it still renders the old partial and no call to the corresponding action is made. Here is my view code:
label.control-label for="color_servers" Colors
.controls
input.input-xxlarge type="text" name="colors" id="project_colors" placeholder="comma separated colors" onblur="getColors(this)"
a data-toggle="modal" id="color_target" href="#" data-target="#color_modal" (Show colors)
.modal.hide#color_modal
.modal-header
button.close type="button" data-dismiss="modal" aria-hidden="true" ×
h3 Color list
.modal-body
.modal-footer
a.btn href="#" data-dismiss="modal" aria-hidden="true" Close
And this is my partial which I am rendering:
ul
- for color in #colors
li #{color}
I'm displaying the partial with the information in a lightbox type display. Here is my javascript code for the onBlur event of the text field:
function getColors(elem){
if(elem.value.trim()){
$.ajax({
url: "/project/check_colors",
type: "GET",
dataType: "json",
data:{
colors: elem.value
},
success: function(data){
$('#color_target').attr('href','/project/show_colors?colors=' + data.color_list)
console.log(document.getElementById("color_target").href)
console.log(data.input)
console.log(data.color_list)
}
});
}
}
So in the javascript code when I look at the output of the href attribute in the console, it shows the correct link. And finally here is my controller code:
def check_colors
colors = params[:colors].gsub(/\s+/, "").gsub(/,+/,",")
colors = colors.chomp(",")
color_list = Color.expand_colorset(colors).map(&:fullname)
render 'index', :json => {
:servers => color_list,
:input => colors
}
end
def show_colors
colors_string = params[:colors]
#colors = colors_string.split(",")
puts #colors
render partial: 'color_list'
end
The color_list variable is an array of colors which I send back in order to update the link with. I know that the show_colors action gets called called the first time because the #colors variable's value is printed in my terminal however when I update the text in the textfield and I click on the link again the action is not being called even though the link gets updated because nothing is printed in the terminal. It seems as if the partial is being cached, if that is the problem how can I prevent that. Also when I try to render my partial as a full fledged view rather than a partial, the action is called correctly every time and it renders the correct information even after changing the text field contents, but when I do that then my lightbox functionality does not work correctly. Any help will be appreciated, thank you.
hi guys for anyone who is interested I figured it out. It is kind of hacky but it works for me. I added this piece of code in my javascript outside of all functions, and it cleared the cached ajax.
$('body').on('hidden', '.modal', function(){$(this).removeData('modal');});
Hopefully it will save someone time in the future.
There is a pretty bootstrap editor - Bootstrap WYSIWYG, which i want to use in my blog based on RoR 4.0. The problem is that Bootstrap WYSIWYG does not work with anything except DIV tag (as far as i know from a bit searching).
This code works fine:
<div id="editor" contenteditable="true">some editable content</div>
And this one doesnt:
<%= f.text_area :content, id: "editor", contenteditable: "true" %>
<textarea id="editor" contenteditable="true">
So, the question is - how to connect this two things together?
have you tried putting a hidden field, working with the div and when the editor have changes update the hidden field value? Hope this helps
In order to integrate Bootstrap-WYSIWYG in a Ruby on Rails app you should do the following:
(most of the times - you have more than one editor in a rails form, in this example I will show how to do it without errors)
I will use the editor in the admin namespace, therefore I have created a folder editor inside my views: "admin/shared/editor" to keep everything tide and content oriented.
Firstly, for every attribute of a model I would like to use the Bootstrap WYSIWYG editor I will render a partial with the field that has integrated the editor, so you might have smth like this:
/admin/posts/_form.html.haml:
= form_for #post do |f|
= render partial: 'admin/shared/editor/field', locals: { f: f, content: "summary" }
= f.button class: "form_with_editor"
were you pass as a local parameter the form and the attribute of the model you would like to apply the editor (in this case => summary). Note also that you should add a class to the submit button of the form: .form_with_editor, that will be used later for the button click listener.
Now inside admin/shared/editor/_field.html.haml:
.btn-toolbar.btn-editor{"data-role" => "editor-toolbar", "data-target" => "#editor_area_for_#{content}"}
= render partial: 'admin/shared/editor/toolbar'
.wysiwyg{id: "editor_area_for_#{content}", style: "overflow:auto; height:444px;max-height:444px", data: {"for-content" => "hidden_#{content}"}}
= f.hidden_field content.to_sym, id: "hidden_#{content}"
This editor works with a div and not with a textarea, therefore, we will be using a div with class .wysiwyg and a dynamic id which in this case evaluates to: #editor_area_for_summary
The class: .wysiwyg is used in order to select all the divs with this class when we initialize the editor in our doc ready function.
The toolbar partial contains all the markup for the custom toolbar of the editor, you can customize it as you wish and use it in all your fields.
In order to copy the contents of the div to the form input and post them to the server, you have to use a hidden input field:
= f.hidden_field content.to_sym, id: "hidden_#{content}"
Note: it also gets a dynamic id(which evaluates to: "hidden_summary") and a name -> :summary
Now in order to make all these to work together we need some javascript on your doc ready function:
/assets/javascripts/doc_ready.js:
$( document ).ready(function() {
// EDITOR stuff
$('.wysiwyg').wysiwyg();
// Handling the form submission
$('.form_with_editor').click(function(){
$('.wysiwyg').each(function() {
var editor_div_content = $(this).html();
var hidden_input = $(this).attr("data-for-content");
$("#" + hidden_input).val(editor_div_content);
});
});
// Fill the editor divs with content
$('.wysiwyg').each(function() {
var hidden_input = $(this).attr("data-for-content");
var editor_div_content = $("#" + hidden_input).val();
$(this).html(editor_div_content);
});
});
On the first part we apply the function wysiwyg() of the editor in every div that has this class.
On the second part we have an on click handler of the form button we get the html content of the div and we set it as the value of our hidden input field.
And on the last part we do the opposite, we get the value of the hidden field and place it on the editors div when the document is ready, with this one we display content on the editor that is already stored in the database.
I hope this one helps :)
I have a view with a bunch of elements in it.One of them (a div) is shown depending of a value that changes inside a select_tag (also within the same page).
I'm getting the selected ID from the select_tag element
$('#some_id').on('change',function(){
//$(this).val()
})
but then just don't know how to fetch the object and check for one of its properties and that way know if I should show the div or not?.
I thought of sending that id to the server...do whatever I need over there and then come back to the view and try something like this
<% if some_condition %>
<div>
...
</div>
<% end %>
This (of course) might not be the way.I'd be glad to understand how this happens
You way of doing it after getting some data from the server onChange of the select would work. You might also consider this approach.
But if you could pre-populate the divs and add a class or some other attribute it with which you could relate to the chosen option in the select field, then you can prevent the server call entirely.
<div class="opt1Val selectOptsDiv"> </div>
<div class="opt2Val selectOptsDiv"> </div>
<div class="opt3Val selectOptsDiv"> </div>
hide all these divs initially with css display: none;.
$('#some_id').on('change',function(){
var selectedOptionVal = $(this).find("option:selected).val();
$("." + selectedOptionVal).show();
})
But I guess you would be able to do this if the showing and hiding of the div's depend only on the selected option value and do not have to go through some other processing at the server end.
Reinstalling a Rails app on a new server. Part of the app can fork in one of two directions based on the button the user selects. This part isn't working, and when I look at the log I see the values that I gave the form, execept for the commit portion of the params hash. This seems to be why the app isn't working as expected (since there's nothing in params[:commit], but I have no idea why commit would not be passed in; the request is definitely a POST request, and all of the other parameters are there.
Had a simular problem with a disable-button-on-submit feature. We solved it by adding a hidden input field with the same name and value before submitting the form.
function disableButtonAndSubmit()
{
var input = $("<input type='hidden' />").attr("name", $(this)[0].name).attr("value", $(this)[0].value);
$(this).closest('form').append(input);
$(this).attr('disabled', 'disabled').html('Loading…');
$(this).closest('form').submit();
}
$('#somewhere button').click(disableButtonAndSubmit);
Just add name: "commit", value: "Save"to your form submit button:
form_for #object do |f|
...
f.button :submit, "Save", name: "commit", value:"Save"
end
and then you will have params[:commit] equals to "Save" in the controller.
I ran into this same problem, and the answers here pointed me in the right direction. However, rather than the suggestions to be adding hidden form inputs or giving up on the double submit block, you can simply add a setTimeout function on your double submit block with a timeout of 1 millisecond, which allows the double submit block to work without preventing the submission of the button.
Check that your submit input is named commit or it's label will not be sent.
The resulting html should be:
<input type="submit" name="commit" label="...>
I looked into something like this awhile ago, where there is inconsistency in how different browsers would pass in the value of a submit button on a form. I found the only practical solution was to have javascript in the button to set a hidden field, and use that value instead.
Here is some of my code to differentiate between a save and exit, which goes one way, and save and continue which go another:
<%= hidden_field_tag 'step_commit', '' %>
<span style="float:left;">
<%=submit_tag 'Cancel', :name=>'cancel', :onclick=>"javascript:location.href='/';return false;" %>
<%=submit_tag 'Save and Exit', :name=>'exit', :onclick=>"javascript:$('step_commit').value='exit';" %>
</span>
<span style="float:right;">
<%=submit_tag 'Save and Continue', :name=>'continue', :onclick=>"javascript:$('step_commit').value='continue';" %>
</span>