0

I have a legacy application written in Vaadin which needs to be ported to Angular 15, notably using the same URL structure. I'm almost done with it. The one thing missing is that I need to check if no URL query param exists on the root path. In this case, I need to display a popup.

Short:

  • http://xxx/?a=1234 <-- this is what the customer will get from the sales person
  • http://xxx/ <-- this should show a popup, like "wrong URL, contact sales"

I am subscribing to the route queryParams in onInit. My first attempt was to simply check for the param's existence within the subscribe block and trigger the action that way. This worked for URLs with no queryParams, but also got triggered if params were existing. I boiled it down, introduced a counter and figured that there were actually two iterations within the subscribe block with params, the first returning an empty object.

Here is the running app:

https://codesandbox.io/p/sandbox/xenodochial-rosalind-3mtpr5

The subscribe part looks like this. Same thing if it's in the constructor():

  ngOnInit(): void {
    console.log('onInit start');
    this.route.queryParams.subscribe((p) => {
      console.log('count:' + this.count + ' => ' + JSON.stringify(p));
      this.params = p;
      this.count++;
    });
    console.log('onInit end');
  }

I would expect something like this if there are query parameters:

onInit start
count:1 => { "a":"1234" }
onInit end

Instead, I get

onInit start
count:1 => {}
onInit end
count:2 => {"a":"1234"}

I tried several things, nothing worked:

  • moved the block to constructor()
  • used snapshot
  • checked if AfterViewInit() would have the final result
  • tried to find a way to wait for the subscribe() to finish
  • duckduckgo'ed a lot
  • ...

Any idea/hint highly appreciated.

Edit: I actually need a way to know when the whole parameter loading process is done, to trigger the popup or continue.

Edit: app.module.ts

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, RouterModule.forRoot([])],
  providers: [],
  bootstrap: [AppComponent],
})

2 Answers 2

1

Router Observable are (BehaviorSubjects) different to RxJS Subject observables. This kind of observables gives you an initial value (what is null, or empty object) first.

The easiest way is to skip the first value.

 this.route.queryParams.pipe(skip(1)).subscribe((p) => {
      console.log('counter:' + this.count + ' => ' + JSON.stringify(p));
      this.params = p;
      this.count++;
    });

For the first params, if you reload the page (not change the url, reload or at first load) you can use the snapshot

 constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    const params: any = this.route.snapshot.queryParams;
    console.log("Params", params);
  }

Important, too: provide Router:

In a standalone component you need to use the new provideRouterfunction!

import { provideRouter } from '@angular/router';
import { bootstrapApplication } from '@angular/platform-browser';

......

bootstrapApplication(App, {
  providers: [provideRouter([])],
});
Sign up to request clarification or add additional context in comments.

10 Comments

This is much more elegant than counting, but in the end, it doesn't solve the issue. When I skip the first value, it won't even jump in there with no parameters. Which means, I still don't have a good spot to trigger the popup.
You need to combine it with the snapshot. Thats the way to go. Snapshot at beginning. And subscribe fires if you change only the params.
Where would I take the snapshot?
In the ngOnInit part.
I have updated my answer. Look to the provideRouterpart.
|
0

Thanks for all your inputs. I found the easiest way to do it (maybe not the smartest):

In app.components.ts, I implement OnInit. In there, I do it the java script way:

if (!window.location.href.includes ...) {

Works and doesn't interfere with anything else.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.