How can I set a session variable from a js inside

2019-08-18 17:17发布

问题:

I have table row shading (for groups of row) via js.
I want to make it so that the shading is remembered through a session variable.

The haml partial I am using has:

Group Shading: 
  %a{:href => '#', :id => 'row_colors_on'}
    On
  %a{:href => '#', :id => 'row_colors_off'}
    Off

the js has:

$(function(){
$("a#row_colors_on").click(function(){
$(".row_color_group_1").addClass("color_group_1");
$(".row_color_group_2").addClass("color_group_2");
$(".row_color_group_3").addClass("color_group_3");
<%- session.group_shading = 'true' %>
event.preventDefault();
});
});
$(function(){
$("a#row_colors_off").click(function(){
$(".row_color_group_1").removeClass("color_group_1");
$(".row_color_group_2").removeClass("color_group_2");
$(".row_color_group_3").removeClass("color_group_3");
<%- session.group_shading = 'false' %>
});
});

the main page then uses:

- row_bg_color_group = 'row_color_group_1'
- for link in @links
  - construct_hyperlink(link.url_address, link.alt_text)
  - if link.group.group_name != (current_group ||= '') 
    - display_group = current_group = link.group.group_name
    - row_bg_color_group = rotate_rows_color_group
  - else
    - display_group = ''
   %tr{:class => "#{row_bg_color_group}"}

The code to change the background color of rows does do it but it is not remembered after a page refresh through the session variable ?

with the helper:

def rotate_rows_color_group
  if session[:group_shading] == 'true'
    cycle('row_color_group_1', 'row_color_group_2', 'row_color_group_3')
  else
   'row_color_group_1'
  end 
end 

but I always get the 'else' condition, i.e. session[:group_shading] is not being either set or recognized

The css is

.color_group_1 { background-color: #133333; }
.color_group_2 { background-color: #122222; }
.color_group_3 { background-color: #111111; }

回答1:

You can't use erb statements within javascript, it is parsed before it is send to a client. Instead use javascript sessionStorage:

$(function(){
$("a#row_colors_on").click(function(){
$(".row_color_group_1").addClass("color_group_1");
$(".row_color_group_2").addClass("color_group_2");
$(".row_color_group_3").addClass("color_group_3");
sessionStore.setItem('group_shading', true);
event.preventDefault();
});
});
$(function(){
$("a#row_colors_off").click(function(){
$(".row_color_group_1").removeClass("color_group_1");
$(".row_color_group_2").removeClass("color_group_2");
$(".row_color_group_3").removeClass("color_group_3");
sessionStorage.setItem('group_shading', false);
});
});

$(document).ready(function() {
  if (sessionStorage.getItem('group_shading'))
    $("a#row_colors_on").click();
});

Important note:

Note however that js session is sth else than your rails session. Rails session can be stored in various places and javascript has no access to it. This means you can't access those values on the server side. There are two solutions:

1) Use sessionStorage and execute some javascript depending on stored value after the page has loaded (as above).

2) Instead of using sessionStorage, send an ajax request to server to populate rails session (recommended).



回答2:

You can share state between Javascript (client-side) and Rails (server-side) with cookies. You can set a cookie in the view via Javascript (check out the js-cookie library), and read the cookies in a Rails controller.

Using the js-cookie library, you could set a cookie: (Cookie.set('awesome', 'sauce')) and then read it in the Rails controller: (puts cookies['awesome']).