On the use of Acl of NG Alain


Recently, angular is always used as a background system. I found the Ng Alain framework for a long time, and it's quite easy to use. It's just that the official document is a little more concise. In the process of using it, we have to combine some small examples and official demo to determine the syntax. The previous use has been very smooth, even if there are some problems, we can find the blog or materials related to the problems on the Internet. But in the past two days, when we used the access control list, we encountered some problems, which took some time and many twists and turns to solve. Although it's outside the framework, we want to take this opportunity to write the first blog. (there are development notes before, but it's easy to write them down in Youdao cloud every time you meet them. I didn't consciously sort them out in my spare time at weekends. In fact, I'm lazy =; I'll sort them out and paste them together later ~ set up a little flag ~)


After the acl parameter is added to the custom button group in the st component, the role will be reset for the first entry and refresh. The reason is that the can() is used to print out false, and the switch route reloads the page to print true, which can display normally. The problem is that there is no way to make the first entry and every refresh display normal.
(acl parameters are also added to the menu data in app-data.json, and the startup.service.ts file has set roles, but no permission points for granularity control are used, all of which are controlled through roles.)

Code display

Parameters of custom button group of st component in API document

Set acl parameter of button group in page


The role is set in the startup file. At the beginning, setRole() is used. I'm afraid that the problem of clearing all roles in each assignment of this function causes the problem of changing to attachRole() to be solved

Console debugging, red box is the output of can() function in ngOnInit in the page

Effect display

With the right logic, entering the widget page should look like this

However, due to the asynchronous role setting, the page refreshed and displayed for the first time is as follows

Then switch the route and then switch back to reload the page. The page displays normally again

Solve the problem


In the process of writing demo, we found the cause of this problem

The reason is that my original user rights are obtained through asynchronous requests. In the process of writing the demo, I used settimeout instead of asynchronous requests. After commenting settimeout in the demo, I found that the problem was solved

Original file:

demo file:


Get the permission variable in advance and store it in localstorage, and get setRole() at startup, so there is no asynchronous problem.

Add the local.storage.ts file to src/app/core/net (the path can be set according to your preference)

// local.storage.ts file contents
import { Provider } from '@angular/core';
export class LocalStorage {
  public localStorage: any;

  constructor() {
    if (!localStorage) {
      throw new Error('Current browser does not support Local Storage');
    this.localStorage = localStorage;

  public set(key: string, value: string): void {
    this.localStorage[key] = value;

  public get(key: string): string {
    return this.localStorage[key] || false;

  public setObject(key: string, value: any): void {
    this.localStorage[key] = JSON.stringify(value);

  public getObject(key: string): any {
    return JSON.parse(this.localStorage[key] || '{}');

  public remove(key: string): any {

Introduce in app.module.ts

login.component.ts file:

// Add content to login.component.ts file

// ...
import { LocalStorage } from '@core/net/local.storage';

// ...

export class UserLoginComponent implements OnDestroy {

    private localStorage: LocalStorage, // Introducing localstorage
  ) {
    // Clear roles every time you enter the landing page

  submit() {

    // ...

        username: this.userName.value,
        password: this.password.value,
      .subscribe((res: any) => {

        // ...

        // Set user Token information
        this.tokenService.set({ token: res.data.token });
          resp => {
            // Save role permissions obtained asynchronously
            this.localStorage.set('role', resp.data.acl);
          () => null,
          () => {
            // Function after execution

            // To retrieve the startups service content, we always believe that the application information is generally affected by the authorization scope of the current user
            this.startupSrv.load().then(() => {
              let url = this.tokenService.referrer.url || '/';
              if (url.includes('/passport')) url = '/';

startup.service.ts file:

Write at the end

This solves the problem of asynchrony, but I always think it may not be the best solution. There are several questions I haven't found out yet: where are the variables set in aclservice stored? Does alain have its own way of writing that I don't need to save in localstorage?

The reason why I found the reason for writing demo is that I delayed two or three days for this problem, baidu did not find the problem when checking the data, but only sent an email to ask Ng Alain's developer card color (the email left on GitHub). Before that, I did consider that it might be asynchronous. After turning the asynchronous request await into synchronous, I found that page rendering precedes the execution of the startup file, and the problem has not been solved. Subconsciously, I thought it was not asynchronous. Then, the debug test to eliminate the write dead parameters of asynchronous requests was not carried out because of such problems. This is the first time I wrote an email to ask the author. I'm really sorry to disturb the God...

Published 1 original article, praised 0, visited 8
Private letter follow

Keywords: JSON angular github

Added by Calamity-Clare on Thu, 12 Mar 2020 11:24:09 +0200