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

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.

Related

Saving a value in a hidden_field_tag with Javascript

I have a form in rails app with a field for choosing a city and saving it's id.
= select_tag 'building[city_id]',
options_for_select(cities.map{|c| [c.name, c.id]}),
onchange: "myFunction();", include_blank: "Choose city"
I want to save a city name in a hidden_field_tag as soon as the user chooses something from a select tag. How do I implement this with Javascript?
I'm very new to Javascript, please don't judge hard.
I suggest doing as little JS as possible. So:
Start by adding the hidden field (with a null value) in your Rails view.
Now you'll need to add Javascript to your pages (you may already have a file at app/assets/javascripts/application.js which is included with all your pages; including JS with your Rails templates is its own question). You'll need two functions, and jQuery will make life a lot easier:
A function which checks the value of the select tag, and updates the value of the hidden tag with the value from the select tag.
A function which runs at page load time which attaches an event listener to the select tag; this will listen for the "change" event on the "select" tag and call our first function when it sees it.
These will look something like this (N.B. this code will almost certainly not work for you without changes):
function setHiddenValue() {
// Get the value from the select tag
var selectValue = $('select#building_city_id').val();
// Set the hidden tag's value to the select tag value we got in the last line
$('input[type=hidden]#city_name').val(selectValue);
}
I'm guessing at the selectors for getting the elements, but Rails is putting IDs on them which you can use.
$(document).ready(function () {
$('select#building_city_id').on('change', setHiddenValue());
}
Obviously this is rough and will not work immediately on being pasted in. You'll want to be sure the selectors match what Rails is putting in your HTML, you'll want to be sure the scripts are getting included in your page and the event listener is being set, you'll need to check that jQuery is present, and you'll want to be sure the setHiddenValue function gets the correct value to put in the hidden form tag. But this is how I'd start out on what you're trying to do; the rest is details which are particular to your page.

rails forms:how do i blur a field when a particular option is selected in another field

This is gonna be my first attempt at javascript. When someone selects a particular option in a select list, I want another field in the form to go dull because it's no longer applicable. I guess I have to write an onchange event handler and have it execute a javascript script that detects the selected option and renders a form with the relevant field dull if the option's selected or renders a different form if a different option was selected ... anyone can give me a start please ~ thanks
You can do this by using change event of jquery.
For example your option select like this:
<%= f.select :state, [['NSW'], ['VIC'], ['SA'], ['WA'], ['QLD']] %>
Then, you have to create jquery event to do your next action. For example:
<script>
$(document).ready(function(){
// hidding form
$("#form_1").hide();
$("#form_2").hide();
// showing form after user changes the select option
$("#user_state").change(function(){
var selected = $(this).val();
if(selected == "VIC") {
$("#form_1").show();
} else {
$("#form_2").show();
}
});
});
</script>
I hope this help you to attempt the first experience for trying jquery. Good luck!
You may try something like this:
$(document).on('blur', "selector", function (e) {
// do what you want to do, change background, color, etc...
});
Instead of selector type in the class, id, or other selector for the element you need to change.
You can add this snippet to any javascript file included in app/assets/javascripts/application.js. You can create a new one and add it there if none existing suits you...
If application.js ends with //= require_tree . it means that it will require all files in that directory and you do not need to manually require them.
Btw, concerning the terminology, element has focus when it is clicked on. When element looses focus (for example some other element is clicked, or tab is pressed), it gets blured. That is when on('blur') gets called.
This is how you can write on('change') for a select:
$(document).on('change', 'select', function (e) {
// do something
});
Instead of 'select' you need to type in the correct selector, otherwise it will get triggered each time any select changes.
I need the action to be triggered only when i specific value in the
select list is selected
No problem, try this:
$(document).on('change', 'select', function (e) {
if ($(this).val() == 'specific_value'){
// do something
}
});
UPDATE
I wanna make the call to jquery from my view and replace the element
in the view with the output of the jquery filename.js.erb file
jQuery, and all other javascript is being executed within the client (the web browser), and your file filename.js.erb is located on the server, and it needs to be processed by rails.
This is how it can be done:
ajax request is sent to the server
it gets picked up by rails, and it is routed to a controller
it is processed by a controller action
a javascript view is rendered and posted as a response
There are two ways to achieve this. First I will explain the steps that are common for both approaches.
You will need to add a new route to your routes.rb that you will use as an endpoint for your ajax call. Here you can read more about adding routes to rails, but for the purpose of this answer, I will use this simple route (with a dumb name, you should change that for sure):
resource :my_ajax, only: :create
And this is what the route looks like:
rake routes|grep my_ajax
# my_ajax POST /my_ajax(.:format) my_ajaxes#create
It expects that you have MyAjaxesController, and within it create action. You should also make your controller able to respond to javascript requests by adding this to the controller:
class MyAjaxesController < AdminController
# ...
respond_to :js
# ...
def create
# ...
end
end
You also need to have a view for that action: create.js.erb. You can add javascript to that view, but there you can also make use of everything rails controller makes available for you. So, you can use any instance variables or you can render partials.
This is how a partial can be rendered:
$('#element').html('<%= j(render partial: "_my_partial", locals: { my_var: #my_var }) %>');
When the response to ajax request is received by the browser, it just replaces the contents of #element with whatever html got rendered by that partial.
Ok, coming now to the differences to the approaches.
You could send an ajax request (by jQuery) aiming to the endpoint that you created (mind the method, the route I created expects POST). In that case you need to manually manage any response you receive.
However, there is a rails way of doing it. You could create a form with all of its fields hidden (you don't need it in the view, you just need it as a means to send a request). You need to specify the action for the form, the method, and also set remote: true, to make sure that it is submitted asynchronously.
Here's an example:
<%= form_tag(my_ajax_path, remote: true, method: :post) do %>
<%= hidden_field_tag :some_field %>
<% end %>
All you need to do is submit this form whenever you want (for example by looking it up with an id and calling submit: $('#my_form').submit(); and it will do the rest. You can also dynamically change any hidden inputs of the form prior to submitting.
$(document).on('change', 'select', function (e) {
if ($(this).val() == 'specific_value'){
$('#my_form').submit();
}
});
As for the testing the controller action by rspec, in order for it to work, do not forget that what controller expects and renders is javascript requests, so you need to specify the format:
it 'my test' do
# expectations
response = post :my_ajax, format: :js
# assertions
end

Django-CKEditor Widget not loading dynamically

I am having problem on loading the second and next ckeditor widget on the front-end form in html. It works well in admin. When I click add more form set dynamically, the widget not come out but showing textarea instead, it just works on the first (initalized) form. I already follow the documentation step by step for basic requirements. I am using Django with django-ckeditor package. Got no javascript errors on the page.
Sorry for not showing any codes before. This is part of the javascript which dynamically adding another form set after button clicked:
<script src="//cdn.ckeditor.com/4.4.5/standard/ckeditor.js"></script>
<script type="text/javascript" src="ckeditor/ckeditor-init.js"></script>
$('#add_more_work').click(function(){
var form_idx = $('#id_form_set-TOTAL_FORMS').val();
$('#form_set_work').append($('#empty_form_work').html().replace(/__prefix__/g, form_idx));
$('#id_form_set-TOTAL_FORMS').val(parseInt(form_idx) + 1);});
The field which use the ckeditor widget not loading after it added dynamically by this button but instead, it shows plain textarea. Did I miss anything?
You might want to look at using the formset:added and formset:removed JavaScript signals available from Django 1.9 onwards.
A simple method (combined from django-content-editor and feincms3 ) might look like this:
(function($) {
$(document).on('formset:added', function newForm(event, row) {
row.find('textarea').each(function() {
CKEDITOR.replace(this.id);
});
});
})(django.jQuery);
I'll leave the handling of formset:removed to the reader.

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});

Autosaving changes to textfields using jquery

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

Categories