Emre Emre - 6 months ago 24
jQuery Question

Rails - Dynamically Login People

I have a rails app and when user clicks to login button on header a bootstrap popup modal opens with a form, asks for user email and password. When user types and presses enter, I use

window.location.reload();
and the button login turns in to a button with a text says
"Welcome <%= current_user.name %>"


What I want to do is, instead of using window location reload, can I update this dynamically?

Here is my
sessions#create
action

def create
user = User.find_by(email: params[:session][:email].downcase)
respond_to do |format|
if user && user.authenticate(params[:session][:password])
if user.activated?
log_in user
params[:session][:remember_me] == '1' ? remember(user) : forget(user)

format.html { redirect_back_or user }
flash[:notice] = t('flash.sessions.create.success.html')
format.js #here I should do smth
else
format.html { redirect_to root_url }
format.json { render json: {email:['Account not activated. Check your email for the activation link.']} , status: :unprocessable_entity}
format.js { render json: {email:['Account not activated. Check your email for the activation link.']}, status: :unprocessable_entity }
end


then the
create.js.erb


// close modal

$('#login-dialog').fadeToggle();
// clear form input elements
// todo/note: handle textarea, select, etc
$('form input[type="text"]').val('');

//Clear previous errors
$('.form-group.has-error').each(function(){
$('.help-block').html('');
$('.form-group').removeClass('has-error');
});

window.location.reload(); #here I am reloading the page then I can see login button disappears and new button saying Welcome Billy appears.


So how can I do that without reloading the window.
Thank you

EDIT

The thing is, I have also signup modal which user can click to open and these modal codes are in header.html.erb, when I render the page as you suggested it gives an error for sign up form;

<% modal ||= false %>
<% remote = modal ? true : false %>
<%= form_for(@user, remote: modal, :html => {role: :form, 'data-model' => 'user'}) do |f| %>


<div class="form-group">
<%= f.label :name, t('header.nameSurname') %>
<span class="help"></span>
<%= f.text_field :name, class: 'form-control' %>
<span class="help-block"></span>
</div>

<div class="form-group">
<%= f.label :username, t('header.username') %>
<span class="help"></span>
<%= f.text_field :username, class: 'form-control' %>
<span class="help-block"></span>
</div>
....


because of
@user
variable, if I change it to
User.new
is it ok?, would it create problem?.

I also have 3 different header partials. I normally render them in application.html.erb as;

<div id="render_main">
<% if @header_main %>
<%= render 'layouts/header_main' %> <!--Header comes here-->
<% elsif @header_listing %>

<%= render 'layouts/header_listing' %> <!--Header comes here-->
<% else %>
<%= render 'layouts/header' %>
<% end %>
</div>


But then in create.js.erb;

// close modal

$('#login-dialog').fadeToggle();
// clear form input elements
// todo/note: handle textarea, select, etc
$('form input[type="text"]').val('');

//Clear previous errors
$('.form-group.has-error').each(function(){
$('.help-block').html('');
$('.form-group').removeClass('has-error');
});

//window.location.reload();


<% if @header_main %>
$('#render_main').html('<%= j render "layouts/header_main"%>')
<% elsif @header_listing %>

$('#render_main').html('<%= j render "layouts/header_listing"%>')
<% else %>
$('#render_main').html('<%= j render "layouts/header"%>')
<% end %>


as I render it can not find @header_main variable I believe, so It does not work as it should be. How can I fix this?.

Main controller;

before_action :show_main_header, only: [:home]
def show_main_header
@header_main = true
end


Considering user login, from main controller home action. But it is probably because I actually run from session#create action. how can I fix it?

EDIT

firstly, thank you Rodrigo,

I have written a function to hold last action;

def location_action_name
if !logged_in?
url = Rails.application.routes.recognize_path(request.referrer)
@last_action = url[:action]
end
end


Then I write to create.js.erb;

<% if (@last_action == "home") %>
$('#render_main').html('<%= j render "layouts/header_main"%>')
<% elsif (@last_action == "listings") %>

$('#render_main').html('<%= j render "layouts/header_listing"%>')
<% else %>
$('#render_main').html('<%= j render "layouts/header"%>')
<% end %>


and worked! in case anyone wonders..

Answer

Let's say that you have an partial view for render the header (app/views/shared/_header.html.erb), what you need to do is rerender this partial and replace the header html:

create.js.erb

// window.location.reload();
$('#header-container').html('<%= j render "shared/header"%>')

EDIT:

If the @header_main and @header_listing variables are used to render the header partial, you'll need to instantiate them in your sessions#create action.

To do this, add the show_main_header filter to SessionsController too.