How to pass/delete array params in HTTP Params with Angular

441 views Asked by At

I have an Array of statuses objects. Every status has a name, and a boolean set at false by default.

It represent checkbox in a form with filters, when a checkbox is checked bool is set at true :

const filters.statuses = [
   { 
     name: "pending", 
     value: false
   }, 
   { 
     name: "done", 
     value: false
   }, 
];

I am using Angular HTTP Params to pass params at the URL.

        filters.statuses.forEach((status) => {
          if (status.value) {
            this.urlParams = this.urlParams.append('statuses[]', status.name);
          }
        });

Url params looks like when a status is checked : &statuses%5B%5D=pending

My problem is when I want to unchecked. I know HTTP Params is Immutable, so, I'm trying to delete the param when checkbox is unchecked, so set to false :

...else {
this.urlParams = this.urlParams.delete('statuses');
}

But, it not works, URL doesn't change. And if I re-check to true after that, the URL looks like :

&statuses%5B%5D=pending&statuses%5B%5D=pending

How can I delete params, if the status value is false, and keep others statuses in URL ? Project on Angular 10.

Thanks for the help.

UPDATE : It works to delete, my param name was not good :

else {
       this.urlParams = this.urlParams.delete('statuses[]', status.name);
     }

But, my other problem, it's when I check 2 or more checkbox, the append function write on URL : &statuses%5B%5D=pending&statuses%5B%5D=pending&statuses%5B%5D=done

1

There are 1 answers

0
Sharikov Vladislav On

I have prepared an example to try to answer your question (If I understand this right way).

You can change the checkboxes state or the URL to play with it. Also, I added helper buttons, which will navigate you to different cases (by changing the URL).

Here is the example: https://stackblitz.com/edit/angular-router-basic-example-cffkwu?file=app/views/home/home.component.ts

There are some parts. We will talk about HomeComponent.

  1. You have ngFor which displays statuses, I handled state using ngModel (you can choose whatever you want).
  2. You have a subscription to the activatedRoute.queryParams observable, this is how you get params and set up checkboxes (the model of the checkboxes)
  3. You have the ngModelChange handler, this is how you change the route according to the checkboxes state

Let's focus on 2 & 3 items.

The second one. Rendering the correct state according to the route query params. Here is the code:

ngOnInit() {
    this.sub = this.activatedRoute.queryParams.subscribe((params) => {
      const statusesFromParams = params?.statuses || [];

      this.statuses = this.statuses.map((status) => {
        if (statusesFromParams.includes(status.name)) {
          return {
            name: status.name,
            active: true,
          };
        }

        return {
          name: status.name,
          active: false,
        };
      });
    });
  }

Here I parse the statuses queryParam and I set up the statuses model. I decide which is active and which is not here.

The third one. You need to update the URL according to the checkboxes state. Here is the code:

// HTML
<ng-container *ngFor="let status of statuses">
  {{ status.name}} <input type="checkbox" [(ngModel)]="status.active" (ngModelChange)="onInputChange()" /> <br />
</ng-container>

// TypeScript
onInputChange() {
    this.router.navigate(['./'], {
      relativeTo: this.activatedRoute,
      queryParams: {
        statuses: this.statuses
          .filter((status) => status.active)
          .map((status) => status.name),
      },
    });
  }

Here you have the ngModelChange handler. When any checkbox is checked/unchecked this handler is invoked. In the handler, I use the navigate method of the Router to change the URL. I collect actual checkboxes state and build the query parameters for the navigation event.

So, now you have a binding of the checkboxes state to the URL and vice versa. Hope this helps.