Shawn Wilson Shawn Wilson - 3 months ago 16
CSS Question

Create a Modal to Add new user from Navbar in bootstrap 3 modal - Rails 5

So I am having an issue creating a user in a modal from my navbar. I want to add the link to allow an administrator to create a new user from a link as opposed to going to users index and use the modal button there.


My nav-bar link:


<li><%= link_to "Add User", new_user_path, remote: true %></li>



My Modal so far:


found in: _create.html.erb

<%= content_tag :div, class: "modal fade", id: "createUser" do %>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<%= form_for(@user, remote: true) do |f| %>
<div class="modal-body">
<div class="row">
<div class="col-xs-12">
FORM HERE
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<%= f.submit "Create New User", :class => 'btn btn-primary' %>
</div>
<% end %>
</div>
</div>
</div>



my create.js.erb


$('#createUser').modal('hide');

$(".email").val('');
$(".password").val('');
$(".f_name").val('');
$(".l_name").val('');
$(".primary_tel").val('');

$('#table_body').prepend('<%= j render partial: 'user_row', locals: {user: @user} %>');
$('#user_row_<%= @user.id %>').hide().fadeIn(1000);



users controller / new action


def new
@user = User.new
end


User form I want to turn into a modal:

<%= form_for(user) do |f| %>
<% if user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

<ul>
<% user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>

<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>

<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>

<div class="field">
<%= f.label :user_ident %>
<%= f.text_field :user_ident %>
</div>

<div class="field">
<%= f.label :f_name %>
<%= f.text_field :f_name %>
</div>

<div class="field">
<%= f.label :l_name %>
<%= f.text_field :l_name %>
</div>

<div class="field">
<%= f.label :primary_tel %>
<%= f.text_field :primary_tel %>
</div>

<div class="field">
<%= f.label :role_id %>
<%= collection_select(:user, :role_id, Role.all, :id, :name, {prompt: true}) %>
</div>

<div class="actions">
<%= f.submit %>
</div>
<% end %>

Answer

I assume you want to display the modal in the index view of UsersController. Add your code in _create.html.erb to the top of users/index.html.erb. Your modal won't display unless you explicitly ask it to. Since you're rendering a form in the modal for @user, you need to define what @user is in index action.

# users_controller.rb

def index
  @users = User.all
  @user = User.new

end

You have specified remote:true in your link to new_user_path, you have to render a js response in the new action.

def new
  @user = User.new
  respond_to do |format|
    format.js #Looks for `users/new.js.erb`
    #other formats
  end
end

Since we already have the modal template in index.html.erb, all you need to do in new.js.erb is to display the modal.

# new.js.erb

$("#createUser").modal('show');

Since you have create.js.erb ready, thats all to be done.

EDIT: If you want to place this link in the navigation bar, you should add the modal template to a partial(say layouts/_new_user_modal.html.erb) and render it in application.html.erb which is common to all the views. Also, you need to make a change to your form. Instead of

<%= form_for(@user, remote: true) do |f| %>

use

<%= form_for(User.new, remote: true) do |f| %>

This way you don't have to define @user in every action of your application (DRY).

Hope this helps!

Comments