0

I have an app that has a login page and a register page, so when I click on a button in both pages it has to change from one to other. That works! but when I added a code to hide a persistent menú the button mentioned befored stopped working.

This code consists of a promise.

I detect that when this part of the code is commented, the app works fine, so maybe the problem is with using promises in this part of the app

On login html

<div class="col-lg-4 col-md-4 col-sm-5 col-xs-5 paddingsLog">
  <a routerLink="/registro" routerLinkActive="active">
      <button type="button" class="btnGeneral btnWhite">Regístrate</button>
  </a>
</div>

The same above for register

On app.module

export class AppComponent {
  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
    private location: Location
  ) {
    this.menuAndTitle();
  }

  public menuAndTitle() {
    let getUrl = new Promise((resolve, reject) => {
      this.router.events.pipe(
        filter(event => event instanceof NavigationEnd)
      ).subscribe(() => {
        console.log("Nav ends" + this.activatedRoute);
        let url = this.location.path();
        resolve(url);
        console.log("URL subscribe: " + url);
      });
    });


    getUrl.then((url: string) => {
        const urlActual = url;
        console.log('Url actual: ' + typeof(urlActual) + ' | ' + urlActual);
        if (urlActual.includes('registro')) {
          this.canShowTemplate = false;
        } else if (urlActual.includes('login')) {
          this.canShowTemplate = false;
        }
      }
    }
  }

What I see is that the promise affects the behaviour of the routerLink directive, is it possible?

Manish Balodia
  • 1,863
  • 2
  • 23
  • 37
dav_mrs
  • 3
  • 1
  • Could you please provide a minimal reproduction of your issue in stackblitz? As it is, its impossible to understand what is the issue. – Jota.Toledo Jun 06 '19 at 20:08
  • https://stackblitz.com/edit/angular-fuf8by here is the code, to replicate the behaviour just click on register or login and the router-outlet does not work, but if the menutittle() on the constructor in app.component is commented, the router-outlet works fine – dav_mrs Jun 06 '19 at 21:22
  • So, when you start at the root URL and then navigate to `register` or `login`, do you expect that the flag value becomes `true`? This wont happen, as the `Promise` was already resolved before the navigation, and a promise cant "emit" more than 1 value. – Jota.Toledo Jun 06 '19 at 21:36
  • No, I understand what you say about promises, but the problem is that when I navigate to register or login, the app does not navigate, remains the same. At this point the conditional has been tested and I can see the hello message but the content of the login module has not been "rendered" – dav_mrs Jun 06 '19 at 21:41
  • NVM, I see the issue. For some reason, when you start at the `/` URL, the routed components arent embedded in the view after navigation takes place. – Jota.Toledo Jun 06 '19 at 21:48
  • To be more specific, the behavior affected is the one of the RouterOutlet directive. – Jota.Toledo Jun 06 '19 at 21:54
  • Somehow, when my variable "canShowTemplate" starts on true and then changes to false, the routerOutlet doesn't work but if the variable started on false and remains on this value or change to true, the routerOutlet works! Idk how to interpretate this behaviour. – dav_mrs Jun 06 '19 at 23:26

1 Answers1

0

Im not able to explain why your current template behaves this way, but I was able to find a workaround by doing the following refactor:

<div *ngIf="canShowTemplate; else not">  
  <p>
    New mode
  </p>
  <router-outlet></router-outlet>
</div>
<ng-template #not>
  <div >  
    <hello name="{{ name }}"></hello>
    <p>
      Start editing to see some magic happen :)
    </p>
    <router-outlet></router-outlet>
  </div>
</ng-template>

Furthermore, the current approach that you use to create that Promise<string> is leak-prone, as the Router.events is never unsubscribed. I suggest the following refactor in your component code:

constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
    private location: Location) {
  }

  ngOnInit() {
    this.menuAndTitle();
  }

  public menuAndTitle() {
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
      take(1),
      mapTo(this.location.path())
    ).toPromise().then((url: string) => {
      console.log('Url actual: ' + typeof (url) + ' | ' + url);
      if (url.includes('register')) {
        this.canShowTemplate = true;
      } else if (url.includes('login')) {
        this.canShowTemplate = true;
      } else {
        this.canShowTemplate = false;
      }
      console.log(this.canShowTemplate);
    })
  }

The working solution can be found in this blitz

Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73