0

I have a service that has this function

getCurrentUserPermissions() {
    return JSON.parse(localStorage.getItem('currentUserPermissions'));
}

Now I create a directive to show and hide menus

*hasPermissions="['stations','users']"

Directive

import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core';
import {SiteService} from "../services/site.service";

@Directive({selector: '[hasPermissions]'})
export class HasPermissionsDirective {

@Input("hasPermissions") conditions: string[];

constructor(private templateRef: TemplateRef<any>,
            private viewContainer: ViewContainerRef,
            private siteService: SiteService
) {
}

ngOnInit() {
    let BreakException = {};
    let result: boolean = true;
    let currentUserPermissions = this.siteService.getCurrentUserPermissions();

    try {
        this.conditions.forEach(function (keyCondition) {
            if (currentUserPermissions[keyCondition] !== true) {
                result = false;
                throw BreakException;
            }
        });
    } catch (e) {
        if (e !== BreakException) throw e;
    }

    if (result) {
        this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
        this.viewContainer.clear();
    }
}
}

How can I watch the this.siteService.getCurrentUserPermissions() for changes? Because now i have to refresh the page to rerender the directive to work, if I change the permissions

Michalis
  • 6,686
  • 13
  • 52
  • 78
  • Possible duplicate of [How can I watch for changes to localStorage in Angular2?](https://stackoverflow.com/questions/35397198/how-can-i-watch-for-changes-to-localstorage-in-angular2). Seems like this is just what you want to do. – Robert Moskal Jul 23 '17 at 19:34
  • Thank you very much – Michalis Jul 23 '17 at 21:13

1 Answers1

0

To make it short:

You can't watch localStorage.

Yet there is stuff you can do:

  • Use an additional angular service layer to access localStorage
  • Hook into localStorage.setItem()

I consider the first option the most elegant if you have control of the entire application code. If the info you need is set by some other code use option 2. e.g:

const set$ = new Subject<any[]>();
const _setItem = localStorage.setItem;
localStorage.setItem = function(...args){
  set$.next(args);
  _setItem(...args);
}

/* filter for actions on 'currentUserPermissions' and map to the actual data */ 
const currentUserPermissions$ = set$
  .filter(([key, item]) => key === 'currentUserPermissions')
  .map(([key, item]) => item)

This replaces localStorage.setItem with a new function that pushes the function arguments to a Subject and then calls the actual localStorage.setItem with the data. It's quite a naive implementation, you might need some error checking, because setItem can throw on several occasions.

j2L4e
  • 6,914
  • 34
  • 40
  • Not sure why this is getting down votes. It's a perfectly valid solution that can be used in a case that's different from what's provided in the dupe linked in _Robert Moskal's_ comment. – j2L4e Jul 24 '17 at 09:00