Reputation: 1437
I have a form to create a new source
on sources#create
on which there is a modal to create a new author
. The user can either create a new author
to assign to the source or select an existing one from a checklist.
Ideally, if they do need to create a new author, the authors#create
form would create the author AJAX-ically and the new author would appear automatically on the checklist of authors that can be associated to the source.
Here is the code for the author selection checkboxes on sources#create
:
<section id="author" class="white h-100">
<h2>Author(s)</h2>
<% if @user_authors.count != 0 %>
<p class="text-center">Select an author to add below or <a data-toggle="modal" data-target="#newAuthorModal">create a new author</a>.</p>
<div id="#authorsChecklist"><%= render partial: "authors/checklist", locals: { f: f } %></div>
<% else %>
<p class="text-center"><a data-toggle="modal" data-target="#newAuthorModal">Create a New Author</a></p>
<% end %>
</section>
With this as the authors/_checklist.html.erb
partial:
<div class="boxed-scroll">
<%= f.collection_check_boxes :author_ids, @user_authors.sort_by(&:last_name), :id, :last_first do |b| %>
<div class="field form-check" style="display: block">
<%= b.check_box class: "form-check-input" %>
<%= b.label class: "form-check-label" %>
</div>
<% end %>
</div> <!-- boxedscroll -->
And this as the modal to create the author:
<!-- New Author Modal -->
<div class="modal fade" id="newAuthorModal" tabindex="-1" role="dialog" aria-labelledby="newAuthorModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="newAuthorModalLabel">Add a New Author</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<%= render partial: "authors/js_form", locals: {author: @new_author} %>
</div>
</div>
</div>
</div>
And here's the create
method:
def create
@author = Author.new(author_params)
@author.user_id = current_user.id
respond_to do |format|
if @author.save
format.html { redirect_back(fallback_location: author_path(@author)) }
format.json { render :show, status: :created, location: @author }
format.js
else
format.html { render :new }
format.json { render json: @author.errors, status: :unprocessable_entity }
end
end
end
And here's authors/create.js
:
$("#authorsChecklist").html("<%= escape_javascript(render partial: 'authors/checklist', locals: { f: f } ) %>");
So far the author does get created successfully:
Started POST "/authors" for ::1 at 2020-01-31 21:23:26 -0800
Processing by AuthorsController#create as JS
Parameters: {"utf8"=>"✓", "author"=>{"first_name"=>"Liz", "middle_initials"=>"", "last_name"=>"Bayardelle", "notes"=>""}, "commit"=>"Save Author Info"}
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/application_controller.rb:5
(0.1ms) BEGIN
↳ app/controllers/authors_controller.rb:32
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/authors_controller.rb:32
Author Create (0.8ms) INSERT INTO "authors" ("first_name", "middle_initials", "last_name", "notes", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["first_name", "Liz"], ["middle_initials", ""], ["last_name", "Bayardelle"], ["notes", ""], ["user_id", 1], ["created_at", "2020-02-01 05:23:26.279449"], ["updated_at", "2020-02-01 05:23:26.279449"]]
↳ app/controllers/authors_controller.rb:32
(0.4ms) COMMIT
↳ app/controllers/authors_controller.rb:32
Rendering authors/create.js
Rendered authors/create.js (0.4ms)
Completed 200 OK in 214ms (Views: 27.8ms | ActiveRecord: 42.7ms)
However, the modal doesn't go away when you hit submit and the author doesn't get added to the checkboxes list (basically the partial doesn't refresh). When you manually hit refresh the author appears perfectly.
Can anyone see how to get this to AJAX properly? The desired behavior is for the modal to disappear when you hit submit and for the checklist partial to AJAX-ically refresh so the author appears.
UPDATE
As per comment suggestions, I added this to the create.js
, which successfully makes the modal disappear, though the partial did not refresh:
$('#newAuthorModal').modal('hide');
I then found this question which revealed I needed to change create.js
to create.js.erb
. This somehow stopped the modal from disappearing but yielded a server error saying:
NameError - undefined local variable or method `f' for #<#<Class:0x00007f9e1e0c0ad0>:0x00007f9e18101d38>:
app/views/authors/create.js.erb:2:in `_app_views_authors_create_js_erb__3387754959944580247_70158492637620'
SECOND UPDATE
After consulting the documentation for collection_check_boxes
, the f.
before collection_check_boxes
is not necessary. I removed it and removed , locals: { f: f }
from my create.js.erb
. The modal now dismisses properly and the error is gone, but I still have to hit refresh to get the name to appear.
Upvotes: 3
Views: 476
Reputation: 1437
In sources#create
there was a typo:
<div id="#authorsChecklist">
Should have been:
<div id="authorsChecklist">
And the controller method needed to include the definition of @user_authors
:
format.js do
@user_authors = Author.where(user_id: current_user.id)
end
Now it works!
Upvotes: 2