Autosaving changes to textfields using jquery - javascript

My question is very similar to this one: Getting an error in jQuery when I try to autosave a form field with an ajax call
But the only problem with me is that my situation is more complex. I have a form which has 2 sections. To each section the user can add rows while inputting their data. Each row has a text field and a select box. I need to update the database values of these text fields and select boxes as they change.
Since these all are added on the fly, their ids are different. Ideally I would like to use onchange for each textfield and select box and call required functions which will make ajax call to update respective values. But when I try calling a function onchange, nothing happens. I am wondering if this use is deprecated in Rails 3 in favour of unobtrusive js.
Here's how my haml for the textfield looks:
= builder.text_field "regular_expenditure", :value => val, :title => builder.object.regular_expenditure > 0 ? "" : '0.00', :size => 7, :class => "defaultText", :onchange => "javascript:sendGivenupAmount('challenge_givenup_items_attributes_#{#given_up.rindex(given_up)}_regular_expenditure', '#{given_up.id}');"
In my js file:
function sendGivenupAmount(){
alert('in function');
}
Am I doing something wrong? Is there any other way to do this?
Thanks in advance for any help
M

Thanks for the support. I think I found a solution. I just made some changes to the view and accessed the elements through DOM in jquery. I could manage getting around it.
Thanks,
M

Related

Getting Select2 Gem to work with ActiveAdmin "Add New" Button

I have a RubyOnRails Application that uses the ActiveAdmin and Select2 Gems. Right now, I have made a search box that after typing two letters, shows possible options from the set given. Here is the code for that:
f.has_many :location_permissions, :allow_destroy => true, heading: 'Users With Access To This Installation' do |app_f|
app_f.input :user, :input_html => { :class => "user_select" }, :collection => User.all.map{ |user| ["#{user.name} (#{user.email})", user.id] }
end
This also creates an "Add New" button below. When the button is clicked, a regular ActiveAdmin dropdown menu appears, but I want the Select2 search menu created above to show up. How do I do this?
Here is the user_select function:
$('.user_select').select2({
minimumInputLength: 2
});
If I click the add new button, so it creates a new form, save that empty field, and then refresh the page, the new form becomes the Select2 search form I want. This leads me to think that Select2 applys its JS and CSS on page load, so is it possible to load that part of the page again through AJAX or some other mechanism? I have no idea how to do so, so if anyone could point me at a resource to do something like that, I would appreciate the help.
I ended up getting it to work with the following code:
$(document).on('has_many_add:after', ->
$('select.user_select').select2({
minimumInputLength: 2
})
)
This is in Coffeescript but the Javascript form of this is very similar, replace the "->" with function(){} . ActiveAdmin has an EventListener called has_many_add:after that is called some time after the button is clicked, and you need to execute your code after this. The code above works since the event can still bubble.
Yes, typically select2 is initialized at page load, which is exactly why you're seeing the behavior you described.
What you're going to need to do is wrap the initializer in another function that gets called after you click the 'Add New' button. I'm unfamiliar with ActiveAdmin, but assuming it's just an AJAX request to add to the form, something like this should work:
$( document ).ready(function() {
setupSelect2();
});
$( document ).ajaxComplete(function() {
setupSelect2();
});
function setupSelect2() {
$('.user_select').select2({
minimumInputLength: 2
});
});
Put all of that in some external js file, include it in application.js, and see if that solves your problem.
from the solution provided in this ActiveAdmin issue
we see how to call javascript / jQuery using ActiveAdmin, for a one off use. Other answers provide ways to include .js files into the ActiveAdmin config.
here is a code snipit for implementing the OP's own solution with Arbre the HTML builder syntax that is used within ActiveAdmin:
script do
raw %(
$(document).on('has_many_add:after', () =>
$('select.user_select').select2({
minimumInputLength: 2
})
)
)
end
This felt helpful since for those who may not be familiar with how to implement JS in ActiveAdmin pages as an option to implement the selected Answer.

Is it possible to override Input::old() to null in a model-binded form in Laravel?

I currently have a form built via Laravel that is bound to a model. However, one of my select boxes also has a onChange() event that triggers an AJAX call elsewhere in the page which renders additional form fields specific to what has been selected.
The problem I'm having is that if the select box is already populated (either by pressing the back button or similar), box will be automatically populated with the old input, but the additional questions will not show until the onChange() event is called. I've even tried an onLoad() event, but that doesn't seem to be called for some reason.
I'm sure there's a different approach I could have taken to avoid getting here from the beginning, but the quickest and easiest solution I can think of is to just override the Input::old() that seems to be built in to the model-bound form in Laravel that pre-populates the field. Or I would just have to use a plain Form::open() and put in the Input::old() to all of the other fields.
Here is a snippet of the form I have currently:
{{ Form::model($student, array('route'=>'user.update')) }}
{{ Form::select('major', array(
'major1' => 'major1'
...
), null) }}
{{ Form::close() }}
Thank you very much.

HTML Drop Down List - tidy up?

I've implemented a html drop down list and all seems to be fine, would just like to tidy it up:
1) When the order screen loads 'Select' appears as the initial option on the drop down. When the user clicks the drop down the 'select' still appears. I would like to hide 'select' when the drop down is being selected, some option in the view I am missing?
2) validation wise, I cant make an order until an option is selected from the drop down. This is fine however where before I was using a text box and got a nice big red error message, now I get nothing, How can I notify the user an option has to be chosen?
<div class="editor-field">
#Html.DropDownListFor(x => x.Selected_BicycleModelId, Model.BicycleModels, "Select")
#Html.ValidationMessageFor(model => model.Order.BicycleModel)
</div>
Update
#Html.ValidationMessageFor(model => x.Selected_BicycleModelId)
has resolved the validation message issue (thanks Roman Ko). anyone ideas on the 'select' dissapearing - JQuery?
Try this:
#Html.ValidationMessageFor(model => x.Selected_BicycleModelId)
When it comes to the 'select' caption, you can try to remove it using - for example - jQuery:
$(document).on('change', '#Selected_BicycleModelId', function () {
$("#Selected_BicycleModelId option[value='']").each(function () {
$(this).remove();
});
});
See jQuery remove options from select for more detailed info.
This is not possible. The <select> element has no ability to provide a placeholder value. As a result, a common workaround, and the same that Razor employs, is to add another option with an empty value attribute. This appears in the dropdown because it is very much an option like any other in that list. It's your form validation, both client-side and server-side that makes it not a "valid" option.
You'll need to provide more information to determine why the validation is no longer working. In particular, the property and any associated attributes from your model would be helpful. See #RomanKo's answer. I don't want to steal his thunder by just posting the same thing here. For my part, I totally missed it.

How to run javascript code in Rails when form submitted via text field?

I define a table of editable text fields in HAML like this:
%table
%tbody
%tr
%td
-hints.each do |hint|
=form_for(level_source_hint, :remote => true) do |f1|
=text_field_tag 'message' + hint.id.to_s,
level_source_hint.hint, class: 'input-xxlarge'
%td{:id => 'sibling' + hint.id.to_s} ...
Note that there is not a submit button. If someone edits the text field and presses return, an update request is sent, which works.
When the user submits the form, I would like to do something in javascript to the sibling node (in the second %td). I've tried adding an :onchange attribute to the form_for tag, but it doesn't show up in the generated html.
While I might be able to bind functions to each of the different forms, doing so would be ugly because I would need to create a different function for each row (the number of which is not known until runtime), and each function would have to hardcode which row it came from (e.g., its hint.id).
Do I really need to create and bind one function for each form, or is there a more elegant solution?
I am using Rails 4.0.3 with jquery-rails 3.1.10 and jquery-ui-rails 4.2.0.
You can actually bind to their parent element and then check which element it was when the event bubbles up to the handler. Something like $('#parent_id').on('change', '.field-class', function(){//your code here dealing with submit});

How can I do AJAX-y conditional show/hide form fields in Rails?

I'd like to show or hide a few fields in a form in Rails, depending on the state of a select field in the form. I don't (currently) need a second database lookup for the fields, so I'm trying to keep it all confined to the view. I have the outline sketched out, but I'm having some trouble with the implementation details.
My initial thought was to use observe_field and call Element.show etc. etc., but then I'd have to write a Javascript conditional. This will probably have to work, but I want to avoid it if I can.
Another approach would be to use observe_field to request a RJS template, and replace_html to insert the fields. Not bad, but since I'm using a form_for block I'd either have to pass the form instance all the way through the RJS template to do it right.
I could also update the record on each pass, and display the form under the new conditions, but that's what I'm trying to avoid. It'd be so much simpler to just do this all in the view.
What am I missing here? What's the accepted practice for conditional show/hide forms in Rails?
As a rails developer, I suggest adhering to the principles of unobtrusive javascript. When it comes to rails, what this usually means is that you shouldn't just write one big view to handle all your functionality. This makes your HTML view easier to develop and maintain, it makes your behavior easier to maintain, and it usually leads to a better understanding of exactly what your application is doing. To that extent, I avoid rails javascript helpers at all costs.
What I would do is split off your behaviour into a javascript file that you code yourself. Using a library such as jquery (my favorite for this sort of thing is lowpro, but I'll be the first to admit to being a bit set in my ways), it's pretty easy to attach an event handler to specific elements (or to a whole class of elements at once).
For a select box, an onChange handler will get fired when the user changes the selection. the selectedIndex property on the element will tell you which option is selected, and the options array will let you look up the associated option. So, in your handler you could do something like the following (using prototype):
function(e) {
var element = Event.element(e)
var index = element.selectedIndex
var option = element.options[index]
if(option.value == "Show fields")
$('hidden-fields').show()
else
$('hidden-fields').hide()
}
I handle the same thing a few different ways:
<%= link_to_function( check_box_tag "model[attribute_name]" ) do |page|
page.toggle :model_attribute_name
end-%>
<span style="display:none;" id="model_attribute_name">
<%= f.text_area :other_conditional_attribute -%>
</span>
or
<%= link_to_function "Conditional Item", :class => "your-style-class" do |page|
page.insert_html :bottom, :other_conditional_attribute, :partial => 'conditional_attribute_partial', :object => Object.new, :locals => {:local_variable => local_variable}
end-%>
The rjs stuff/prototype helpers are awesome.
Rails API: PrototypeHelpers
Rails API: JavascriptHelpers
I would suggest using a simple JQuery function along the lines of:
$('a#slick-show').click(function() {
$('#slickbox').show('slow');
return false;
});
For the basics of show/hide in Jquery, there is a tutorial here.

Categories