Rails Ajax partials passing form builder - javascript

I am loading part of my form with ajax depending on the value of a dropdown as follows:
..form_partial.js.erb
$('#custom_ajax').remove();
<% if #house == "Rent" %>
$('#rest_of_form').after('<div id="custom_ajax"><%= escape_javascript render('/houses/forms/rent') %></div>');
<% else %>
$('#rest_of_form').after('<div id="custom_ajax"><%= escape_javascript render('/houses/forms/buy') %></div>');
<% end %>
It is called here...
.._form.html.erb
<%= form_for #house, :validate => true, :html => { :class => 'form-horizontal',:multipart => true } do |f| %>
..........................................
..........................................
<div id = "rest_of_form"></div>
<div id="custom_ajax">
..........................................
..........................................
</div>
..........................................
..........................................
<script type="text/javascript">
$(document).ready(function() {
$('#house_listing_type').change(function() {
$.ajax({ url: '/houses/' + this.value + '/form_partial' });
});
});
</script>
I then can load in the files with that, and it works great the only problem being I need to pass the form builder to the partial as my _buy.html.erb looks like this
<div class="control-group">
<%= label :property_classification, "Property Classification", :class => "control-label" %>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-info-sign"></i></span>
<%= select :property_classification, ["Residential","Commercial"], {},{:class=>"input-medium"} %>
</div>
</div>
</div>
Which obviously needs the form builder, I have tried passing it through as a local etc. but to no avail. I have also attempted removing all the "f." this works, but the form is not displayed correctly, and none of the fancier form builder elements work..
How can I get the form builder to the partial?
Thanks

http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
When not relying on form_for, the form builder elements to be used arelabel_tag and select_tag respectively.
You may find it easier to use both form_tag and fields_for in this case, rather than form_for.

I answered the same question with my proposed solution here:
pass form builder in remote_function in rails?

Related

Summernote editor not working with nested forms

I'm trying to use cocoon-gem and summernote-gem in my ruby-on-rails app.
This is my model:
class Dog < ApplicationRecord
has_many :pictures, as: :imageable, dependent: :destroy
accepts_nested_attributes_for :pictures, reject_if: :all_blank, allow_destroy: true
end
At first look new or edit page seems alright. First summary field render with summernote correctly. And if I already have several pictures saved to my dog model, they all look perfectly fine on editing page.
But when I click on "add picture" it creates new picture field with summary field not rendered properly with summernote. In html page it looks like this:
<div class="field">
<label class="string optional" for="dog_pictures_attributes_1544609860934_summary">Summary</label>
<textarea data-provider="summernote" name="dog[pictures_attributes][1544609860934][summary]" id="dog_pictures_attributes_1544609860934_summary"></textarea>
</div>
Instead of this:
<div class="field">
<label class="string optional" for="dog_pictures_attributes_1_summary">Summary</label>
<textarea data-provider="summernote" name="dog[pictures_attributes][1][summary]" id="dog_pictures_attributes_1_summary" style="display: none;"></textarea>
<div class="note-editor note-frame">...</div>
</div>
This is my _form.erb: (if relevant)
<%= simple_form_for #dog, defaults: { required: false } do |f| %>
<div class="field">
<%= f.label 'Note' %>
<%= f.text_area :note, 'data-provider': :summernote %>
</div>
<h2> Add pictures </h2>
<%= f.fields_for :pictures do |picture| %>
<%= render 'picture_fields', :f => picture %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add picture', f, :pictures %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And this is my _picture_fields.erb:
<div class='nested-fields'>
<div class="field">
<%= f.file_field :image %>
</div>
<div class="field">
<%= f.label :author %>
<%= f.text_field :author %>
</div>
<div class="field">
<%= f.label :summary %>
<%= f.text_area :summary, 'data-provider': :summernote %>
</div>
<%= link_to_remove_association "remove picture", f %>
</div>
I also tried to build nested form from scratch with drifting ruby. But it cause the same problem
When dynamically inserting items into the page, you will have to initialize the summernote editor on those items as well. Cocoon has callbacks to allow you to do this.
When loading the page, to initialize summernote, you would do something like
$('[data-provider="summernote"]').each ->
$(this).summernote
(copied from the summernote-rails gem documentation)
But this only works for the "summernote"'s already on the page, it cannot initialize notes that are not yet there.
So, after inserting a nested-items we have to use the same code to initialise the inserted notes. Something like this should work:
$('form').on('cocoon:after-insert', function(e, insertedItem) {
insertedItem.find('[data-provider="summernote"]').each(function() {
$(this).summernote();
})
});
This will look for summernote items in the freshly nested-item and initialise those.
[EDIT: improve javascript to extract it from view]
Javascript files are generally grouped in app/assets/javascripts, if you are editing Dogs let's add a new file dogs.js and enter the following code:
$(document).on('cocoon:after-insert', 'form', function(e, insertedItem) {
insertedItem.find('[data-provider="summernote"]').each(function() {
$(this).summernote();
})
});
Then add this file to your application.js using require dogs.
This code registers an event handler on the document, it will listen to any cocoon:after-insert event triggered on a form. If you have multiple forms using cocoon, you might need a better/more precise css selector (e.g. add a class to the form and add that as well).

Javascript not executing after Rails redirect

My application contains a very simple login and two separate AJAX calls. I have a loading spinner that is hidden automatically whenever a page is ready it is contained in index.js
$(function() {
$("loading").hide();
$("#scan_button").on("ajax:success", function(e, data, status, xhr) {
$("#standard_results").hide();
$("#results").show();
$("#results").html(data);
});
$(document).ajaxStop(function() {
$("#loading").hide();
});
$(document).ajaxStart(function() {
$('#loading').show();
});
});
When a user logs in the following happens
class SessionController < ApplicationController
def create
user = User.find_by(username: params[:session][:username])
if(user.password == params[:session][:password])
log_in user
redirect_to root_path
end
end
def destroy
logout
redirect_to root_path
end
end
The route path takes me back to 'home#index' for which the index.js file exists. When the user logs in the redirect happens and the loading spinner is hidden and all JavaScript executes as expected.
When the user hits log out however the redirect occurs, but the loading spinner is shown and no JavaScript ever gets executed. Here is my index.html.erb file that contains the JavaScript.
<% content_for :title, "Network Monitor" %>
<div class="container-fluid">
<nav class="navbar narvbar-dark bg-inverse">
<span class="navbar-brand">Network Monitor</span>
<%= link_to "Scan", scan_path, remote: true, class: "btn btn-secondary", id: "scan_button" %>
<% if logged_in? %>
<span class="pull-xs-right"><%= link_to "Logout", logout_path, class: "btn btn-secondary" %></span>
<% else %>
<%= form_for(:session, url: login_path, :html => {:class => 'form-inline pull-xs-right'}) do |f| %>
<%= f.text_field :username, class: 'form-control', placeholder: "Username" %>
<%= f.password_field :password, class: 'form-control', placeholder: "Password" %>
<%= f.submit "Log in", class: 'btn btn-primary', id: 'login_button' %>
<% end %>
<% end %>
</nav>
<div id="loading">
<%= image_tag "loading.gif", class: "loading_gif" %>
</div>
<div class="row">
<div class="col-md-12">
<div id="scan_bar">
<h3>Welcome to your network monitor!</h3> <br />
<p>To get started hit the scan button in the top right corner, this will detect the computers that are alive on your network and show them below.</p>
</div>
</div>
</div>
<div class="row">
<div id="results">
</div>
<div id="standard_results">
</div>
Solved. It was as simple as using
$(document).on('turbolinks:load', function() {});
Instead of what I had posted, this seems to be the way that Rails 5 and turbolinks want you to use, and it worked.
According to the
turbolinks document, I use the event page:change to solve the problem:
$(document).on("page:change", function(){...});
It works for me.
In case others run into this. If you are using an href or link_to try doing something like this:
<li><%= link_to "Home", jobs_path, method: :get %></li>
...where you specify the get method in the request.

How to pass <li> elements to form in ruby on rails

Currently in my ruby on rails project, my events/new.html.erb looks like this:
<h2>Neuer Event</h2><br>
<div id="kalendi">
<%= render 'kalendi' %>
</div>
<ul class="lista">
</ul>
<%= simple_form_for(#event) do |f| %>
<%= f.input :name %>
<%= f.input :content %>
<%= f.input :date%>
<%= f.input :tag_list, as: :check_boxes, collection: ['Logik', 'Ethik', 'Metaphysik'] %><br>
<%= f.button :submit %>
<% end %>
<script>
$(document).ready(function(){
$(document).on('click', ".btn2", function () {
var buttonContent = $(this).html();
$(".lista").append("<li>" + buttonContent + "</li>");
});
});
</script>
The div "kalendi" generates a calendar, where the user can pick out some dates. Let's say, the user has chosen "2016-02-08", "2016-02-09" and "2016-02-10". The <ul class="lista"> looks like this:
<ul class="lista">
<li>2016-02-08</li>
<li>2016-02-09</li>
<li>2016-02-10</li>
</ul>
I want that, when the user presses the submit-button, that the input of <%= f.input :date%> is an array of the chosen dates. What do I need to do? Thanks in advance!
Edit: I heard, that it isn't easy to pass an array from the simple_form gem to the controller. Let's change my question a bit: What do I need to do, so the controller gets a string like this: "2016-02-08, 2016-02-09, 2016-02-10"?
Edit 2, trying to follow the advice of Albert Paul:
I added a hidden field like this:
<%= simple_form_for([#event, #dateevent]) do |f| %>
<%= f.input :date, :as => :hidden, :input_html => { :value => ".alist" } %>
<%= f.button :submit %>
<% end %>
And just for testing, I created a div called alist:
<div class="alist">abcdefghijklmnopqrstuvwxxxxz</div>
At the moment, the value of date is ".alist". What do I need to type in XXX { :value => "XXX" }, to get the content of the div? I tried something like this:$(".alist").val(), but it didn't work. Thanks in advance!
Edit3: Nevermind, I found a solution.
Rails would only pickup input tags as params, but we can do a hack and get those elements by using Javascript. Add a hidden field to your form, and add a click event to your submit button, when user submit your page use jquery to copy contents of <li></li> to this hidden field, so when it gets submitted you'll get your values inside your hidden field.
hidden_field(:signup, :pass_confirm)
http://apidock.com/rails/ActionView/Helpers/FormHelper/hidden_field
Use jquery text() to get contents of <li>
http://api.jquery.com/text/
Not the preferred way to do this, I recommend using rails checkbox tag.

Form Jquery Functions

I am trying to show div by clicking on a button form. I know its wrong just not to sure what to write, and should i write it on my javascript page or just in the view.
<%= submit_tag "Next Step", :type => 'button', :onclick => '$('#devregothinf').hide();' %>
<div id="devregothinf">
<h2>General Information</h2>
<%= render 'geninfor_step', form: f %>
</div>
i am getting an error as follow
syntax error, unexpected $end, expecting ')'
Write as following:
<span onclick = "$('#devregothinf').slideToggle('slow');"> Next Step </span>
<div id="devregothinf" style="display:none;">
<h2>General Information</h2>
<%= render 'geninfor_step', form: f %>
</div>
If you're trying to get it to show and not hide, you just need to change $('#devregothinf').hide(); to $('#devregothinf').show();
You could do something like this
view (app/views/home.html.erb)
<%= link_to 'Next Step', 'home/next_step', :remote => true %>
<div id="devregothinf">
controller (app/controllers/home_controller.rb)
def next_step
<your code>
respond_to do |format|
format.js
end
end
*view (js.erb) (app/views/next_step.html.erb)*
$("#devregothinf").html("<%= raw escape_javascript(render(:partial => 'form')) %>")
*view (app/views/_form.html.erb)*
Your form partial
HTH

How to create a rails form with checkboxes which uses GET?

The intended URL is
"versions/compare/id1/id2"
Obviously, this doesn't work, but shows the intention
<%= form_tag("/versions/compare/", :method => "get") do %>
<% versions.each do |v| %>
<% v.id == #version.id ? current_class = " current" : "" %>
<li class="version-list <%= current_class %>">
<%= check_box_tag(:compare_version, v.id) %>
<%= link_to v.user.name, version_path(v) %>,
</li>
<% end %>
<%= submit_tag("Compare") %>
<% end #form tag
%>
The code above produces http://localhost:3000/versions/compare/?utf8=%E2%9C%93&compare_version=13&compare_version=12&commit=Compare
Is there a way to modify the form (+ JS?) so that it gets the desired URL?
"versions/compare/id1/id2"
you need to understand how form_tag work, it can not change the url after rendering the document.
If you want to change the url, use jquery to change it.
Or, just submit the form into some other url like
<%= form_tag("/comparing_version")
and then, in the controller, after processing everything, you redirect user to
"versions/compare/id1/id2"

Categories