Search code examples
javascriptember.jssession-storage

Ember.js 5.4 how to update component variable when session store is updated


Ember.js Octane and JavaScript (not TS)

I have a service to access the session store. When I add or remove a specific key, I want my top level component to toggle visibility for the nav-bar. I have tried variations of tracking, etc. I attempted to get an observer working, but frankly, I don't understand it, and I'm not sure if that's what I need.

When the store is updated, and then I manually press F5, the application shell then sees the change.

When I call setAuthenticationToken(value), I want the applcaiton-shell to notice the change.

How do I make it so that the application-shell sees the change on its own?


application-shell .hbs & .js

{{#if this.isAuthenticated}}
<nav class="mt-8">...</nav>
{{/if}

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking'
import { inject as service } from '@ember/service';

export default class ApplicationShellComponent extends Component {
    @service SessionManager
    @tracked isAuthenticated = this.SessionManager.isAuthenticated
}

service.js

const SessionId_Key = 'SIDK'
export default class SessionManagerService extends Service {

    @tracked isAuthenticated = this.getAuthenticationToken()
    
    delAuthenticationToken()     {        this.delItem(SessionId_Key)        }
    getAuthenticationToken()     { return this.getItem(SessionId_Key)        }
    setAuthenticationToken(value){        this.setItem(SessionId_Key, value) }

    delItem(key)        {        sessionStorage.clear  (key)        }
    getItem(key)        { return sessionStorage.getItem(key)        }
    setItem(key, value) {        sessionStorage.setItem(key, value) }
}

Updated with answer: Simply setting the isAuthenticated in the del/set Authentication methods is what I needed.

delAuthenticationToken() {        
  this.delItem(SessionId_Key);
  this.isAuthenticated = false;      
}

setAuthenticationToken(value) {
    this.setItem(SessionId_Key, value);
    this.isAuthenticated = true;
}

Solution

  • isAuthenticated is only set once

        @tracked isAuthenticated = this.SessionManager.isAuthenticated
    

    this means, the variable isAuthenticated is initialized with the value from sessionManager (not that isAuthenticated always prepresents the value on the right side of = (as assignments only happen once)).

    to make it reactive, you'll want to convert it a gatter.

    get isAuthenticated() {
      return this.SessionManager.isAuthenticated;
    }
    

    otherwise, if you want to keep @tracked isAuthenticated, one of your functions will need to set the value.

    In either case, your template

    {{#if this.isAuthenticated}}
      <nav class="mt-8">...</nav>
    {{/if}
    

    would then update as expected


    Your overall code would look like this:

    application shell hbs

    {{#if this.isAuthenticated}}
      <nav class="mt-8">...</nav>
    {{/if}
    

    application shell js

    
    import Component from '@glimmer/component';
    import { tracked } from '@glimmer/tracking'
    import { inject as service } from '@ember/service';
    
    export default class ApplicationShellComponent extends Component {
        @service SessionManager
    
        get isAuthenticated() {
            return this.SessionManager.isAuthenticated;
        }
    }
    

    service:

    const SessionId_Key = 'SIDK'
    export default class SessionManagerService extends Service {
    
        @tracked isAuthenticated = this.getAuthenticationToken()
        
        delAuthenticationToken() {        
          this.delItem(SessionId_Key);
          this.isAuthenticated = false;      
        }
        
        getAuthenticationToken() { 
            return this.getItem(SessionId_Key);
        }
    
        setAuthenticationToken(value) {
            this.setItem(SessionId_Key, value);
            this.isAuthenticated = true;
        }
    
        delItem(key)        {
            sessionStorage.clear(key);        
        }
    
        getItem(key)        { 
            return sessionStorage.getItem(key);        
        }
        setItem(key, value) {        
            sessionStorage.setItem(key, value);
        }
    }