Background: I have a login form with a register button, the register button opens a modal where someone can register for an account (you don’t say ). I use a session controller for logging in, and the view for that controller houses the login form as well as the registration modal.
If I open the registration modal, enter invalid data, then click register; theuser_controller
’s :create
action is picking up this request then rendering the session_controller
’s new_view
with the invalid changeset, my problem here is that it re-renders the whole page, changes the url, and nukes my modal, is there a way that I can avoid the url change, and the re-rendering of the entire page, like some sort of data refresh? If I click register again, I can see the validation errors but this is obviously not how it should be. Any help is appreciated.
My code is as follows:
“new.html.eex” for my session view looks like this, I realise that this is a mix of ideas on a single page but I’m not sure how I can make this better so suggestions are welcome.
<div class="login-container">
<div class="login-form">
<div class="d-logo"></div>
<%= form_for @conn, page_path(@conn, :index), [as: :session, class: "login-form"], fn f ->%>
<div class="input-group">
<span class="input-group-addon">
<i class="glyphicon glyphicon-user"></i>
</span>
<%= text_input f, :username, placeholder: "Username", class: "form-control" %>
</div>
<br>
<div class="input-group">
<span class="input-group-addon">
<i class="glyphicon glyphicon-lock"></i>
</span>
<%= password_input f, :password, placeholder: "Password", class: "form-control" %>
</div>
<br>
<%= submit "LOGIN", class: "btn btn-primary" %>
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#registrationModal">
REGISTER
</button>
<% end %>
</div>
</dv>
<div class="modal fade" id="registrationModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="exampleModalLongTitle">Register</h2>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<%= form_for @changeset, user_path(@conn, :create), fn f -> %>
<div class="modal-body">
<div class="form-group">
<%= text_input f, :name, placeholder: "Name", class: "form-control" %>
<%= error_tag f, :name %>
</div>
<div class="form-group">
<%= text_input f, :username, placeholder: "Username", class: "form-control" %>
<%= error_tag f, :username %>
</div>
<div class="form-group">
<%= password_input f, :password, placeholder: "Password", class: "form-control" %>
<%= error_tag f, :password %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<%= submit "Register", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
and when I render the above template from the session controller, it’s like this
defmodule CandidateTrackerWeb.SessionController do
use CandidateTrackerWeb, :controller
alias CandidateTracker.Accounts
alias CandidateTracker.Accounts.User
def new(conn, _params) do
changeset = Accounts.change(%User{})
render(conn, "new.html", changeset: changeset)
end
end
and in the user controller that receives the changeset, upon pressing register I’m doing this
defmodule CandidateTrackerWeb.UserController do
use CandidateTrackerWeb, :controller
alias CandidateTracker.Accounts
def create(conn, %{"user" => user_params}) do
result = Accounts.register(user_params)
case result do
{:ok, user} ->
conn
|> CandidateTracker.Auth.login(user)
|> redirect(to: page_path(conn, :index)) # work in progress, this is a placeholder
{:error, changeset} ->
render(conn, CandidateTrackerWeb.SessionView, "new.html", changeset: changeset)
end
end
end