0
votes

I have created a simple web (stencil) component AuthGuard, not to be be confused with Angular's AuthGuard.

The purpose of this component is to check if the user is logged in.

  • If yes, render the slot html.
  • If not, render the Signup button.

The component code is as follows:

import { Component, Host, h }   from    '@stencil/core';
import { Build, State       }   from    '@stencil/core';

import { AuthService        }   from    'auth/auth.service';
import { ConfigService      }   from    'common/config.service';

@Component({
    tag                         :   'auth-guard',
    styleUrl                    :   'auth-guard.css',
    shadow                      :   true,
})
export class AuthGuard {

    @State() canRender          :   boolean             =   false;

    componentWillLoad() {
        if (Build.isBrowser) {
            const timerId       =   setInterval(() => {
                if (AuthService.isInitialized) {
                    AuthService.vol$.subscribe(_u => {
                        this.canRender= true;
                    });
                    clearInterval(timerId);
                }
            }, ConfigService.loadTime);
        }
    }

    render() {
        console.log('auth guard :: render', this.canRender, AuthService.me);
        return (
            <Host>
                { 
                    this.canRender ? (
                        AuthService.me && AuthService.me.id.length > 0 ? (
                            <slot></slot>
                        ) : (
                            <ion-button
                                href="/signup"
                                routerDirection="forward"
                                color="danger">
                                Signup
                            </ion-button>
                        )
                    ): null
                }
            </Host>
        );
    }

}

Now in the other file, I use the following code:

<auth-guard slot='end'>
    <volunteer-mini volunteer={AuthService.me}></volunteer-mini>
</auth-guard>

With this what I am expecting is

  • Nothing to be rendered, till this.canRender becomes true.
  • Once this.canRender becomes true, If AuthService.me is valid, render the slot HTML,
  • If AuthService.me is null, render signup button.

But seems when this.canRender is false, it tried to render volunteer-mini the slot HTML, which is a problem. Since volunteer-mini internally depends on AuthService.me, which is not yet initialized.

But once this.canRender becomes true, other 2 scenarios are working fine.

1

1 Answers

2
votes

It's in general a bad idea to write an auth-guard using stencil. The core problem is that your slot exists before your component has initialized.

Therefor, using your current code, you'd have to manually remove the slot after you decided that you don't have the rights.

Additionally, if you do not define a slot position, but still provide a slot-content in your parent, it will still be appended to your inner children.

To resolve this problem, you can refactor your component to an function, like <Host>, but this has other pits to consider.