Search code examples
angularhtmlarchitectureangular-routingangular-router

Angular 6 routing multiple parameters based on several different api calls within the same component, is this just bad design?


I've made a single page application in Angular 6, its got 4 levels of metadata that you select and at the end it builds a table with documents based on that selection.

The very first set of buttons are initialised through a HTTP get and then iterated with ngFor. Each of these buttons have their own attributes. The final button which generates the table has 4 custom attributes that it sends with the HTTP call as parameters to the backend which in turn produce a relevant array of documents.

Now the problem that I'm having is that I'd like to be able to have routes every step of the way based on result and be able to link to incomplete queries or at least to the final document table.

As I started looking into how I can create the routing logic behind this I simply ended up confused by how this could possibly work and ended up back at the drawing board.

The question is, what would be the best way to do this? Is there a way to adapt my implementation so far or should I just redesign it? Maybe split it by components? or stop using attributes for storing parameters as I go along and instead access the routing params on the controller? Here's an example on how the final table is generated:

Front-end:

    <mat-step>
  <ng-template matStepLabel>
    <h4>
      {{ step3 }}
    </h4>
  </ng-template>
  <div fxLayout="row" fxLayoutGap="10px" fxFlex="90%" fxLayoutAlign="start center" id="lvl3row">
    <div class="list-group" *ngFor="let button of lvl3">

      <!-- LVL3 buttons -->
      <button matStepperNext [attr.data-param1]="button['md:0/413349530_Level 0 – Section'] |lvl0clean" [attr.data-param2]="button['md:0/413349601_Level 1 – Series Header'] |lvl1clean"
        [attr.data-param3]="button['md:0/413349649_Level 2 – Series Sub Header'] | lvl1clean" [attr.data-param4]="button['md:0/413349651_Level 3 – Location'] | lvl1clean"
        [routerLink]="['docs', button['md:0/413349530_Level 0 – Section'] | lvl0clean | routeCleanPipe ]" mat-raised-button
        color="accent" class="btn btn-secondary" (click)="reveallvl5($event)">
        {{ button['md:0/413349651_Level 3 – Location'] | lvl1clean }}
      </button>
    </div>
  </div>
</mat-step>

Controller:

  reveallvl5($event) {
   this.service
   .generateTable(
    $event.target.attributes["data-param1"].value,
    $event.target.attributes["data-param2"].value,
    $event.target.attributes["data-param3"].value,
    $event.target.attributes["data-param4"].value
  )
  .subscribe(data => {
    this.lvl5docs = data;
    console.log(data);
    console.log($event.target.attributes["data-param1"].value);
    console.log($event.target.attributes["data-param2"].value);
    console.log($event.target.attributes["data-param3"].value);
    console.log($event.target.attributes["data-param4"].value);
  });
  }

Service:

generateTable(param1, param2, param3, param4) {
let headers = new HttpHeaders();

headers = headers.append(
  "Authorization",
  "Basic " + btoa("a14api:testPass")
);
headers = headers.append(
  "Content-Type",
  "application/x-www-form-urlencoded"
);

const params = new HttpParams()
  .append("lvl1param", param1)
  .append("lvl2param", param2)
  .append("lvl3param", param3)
  .append("lvl4param", param4);

return this.http.get(this.ROOT_URL + "lvl5docs", { params, headers });
}

Solution

  • Months of learning later I can say it was indeed bad design.

    Ended up implementing a redux architecture with reducer enhancer to store the states of the application as you make web requests.