user5096599
user5096599

Reputation:

I am using a bunch of *ngIf, is there a better way to do it?

I have a side navigation that is not routing, but populating a content area. I am using a whole bunch of *ngIf on the template, but was wondering if there were a better approach? Perhaps something like <app-{{display}}></app-{{display}}> I'll will show the code from the template and you will be able to understand what I am asking better.

The template is:

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-md-block col-md-2 sidemenu">
      <app-sidemenu [state]="displayContent" (event)="setDataFromSideMenu($event)"></app-sidemenu>
    </div>
    <div class="col-md-10 main-content">
      <div class="jumbotron">
        <h1>Angular Project 1</h1>
        <div *ngIf="display === 'introduction'">
          <app-introduction></app-introduction>
        </div>
        <div *ngIf="display === 'download'">
          <app-download></app-download>
        </div>
        <div *ngIf="display === 'contents'">
          <app-contents></app-contents>
        </div>
        <div *ngIf="display === 'browser-and-devices'">
          <app-browser-and-devices></app-browser-and-devices>
        </div>
        <div *ngIf="display === 'javascript'">
          <app-javascript></app-javascript>
        </div>
        <div *ngIf="display === 'theming'">
          <app-theming></app-theming>
        </div>
        <div *ngIf="display === 'build-tools'">
          <app-build-tools></app-build-tools>
        </div>
        <div *ngIf="display === 'webpack'">
          <app-webpack></app-webpack>
        </div>
        <div *ngIf="display === 'accessibility'">
          <app-accessibility></app-accessibility>
        </div>
        <div *ngIf="display === 'overview'">
          <app-overview></app-overview>
        </div>
        <div *ngIf="display === 'grid'">
          <app-grid></app-grid>
        </div>
        <div *ngIf="display === 'media-object'">
          <app-media-object></app-media-object>
        </div>
        <div *ngIf="display === 'utilities-for-layout'">
          <app-utilities-for-layout></app-utilities-for-layout>
        </div>
        <div *ngIf="display === 'reboot'">
          <app-reboot></app-reboot>
        </div>
        <div *ngIf="display === 'typography'">
          <app-typography></app-typography>
        </div>
        <div *ngIf="display === 'code'">
          <app-code></app-code>
        </div>
        <div *ngIf="display === 'images'">
          <app-images></app-images>
        </div>
        <div *ngIf="display === 'tables'">
          <app-tables></app-tables>
        </div>
        <div *ngIf="display === 'figures'">
          <app-figures></app-figures>
        </div>
        <div *ngIf="display === 'alerts'">
          <app-alerts></app-alerts>
        </div>
        <div *ngIf="display === 'badge'">
          <app-badge></app-badge>
        </div>
        <div *ngIf="display === 'breadcrumb'">
          <app-breadcrumb></app-breadcrumb>
        </div>
        <div *ngIf="display === 'buttons'">
          <app-buttons></app-buttons>
        </div>
        <div *ngIf="display === 'button-group'">
          <app-button-group></app-button-group>
        </div>
        <div *ngIf="display === 'card'">
          <app-card></app-card>
        </div>
        <div *ngIf="display === 'carousel'">
          <app-carousel></app-carousel>
        </div>
        <div *ngIf="display === 'collapse'">
          <app-collapse></app-collapse>
        </div>
        <div *ngIf="display === 'dropdowns'">
          <app-dropdowns></app-dropdowns>
        </div>
        <div *ngIf="display === 'forms'">
          <app-forms></app-forms>
        </div>
        <div *ngIf="display === 'input-group'">
          <app-input-group></app-input-group>
        </div>
        <div *ngIf="display === 'jumbotron'">
          <app-jumbotron></app-jumbotron>
        </div>
        <div *ngIf="display === 'list-group'">
          <app-list-group></app-list-group>
        </div>
        <div *ngIf="display === 'modal'">
          <app-modal></app-modal>
        </div>
        <div *ngIf="display === 'navs'">
          <app-navs></app-navs>
        </div>
        <div *ngIf="display === 'navbar'">
          <app-navbar></app-navbar>
        </div>
        <div *ngIf="display === 'pagination'">
          <app-pagination></app-pagination>
        </div>
        <div *ngIf="display === 'popovers'">
          <app-popovers></app-popovers>
        </div>
        <div *ngIf="display === 'progress'">
          <app-progress></app-progress>
        </div>
        <div *ngIf="display === 'scrollspy'">
          <app-scrollspy></app-scrollspy>
        </div>
        <div *ngIf="display === 'tooltips'">
          <app-tooltips></app-tooltips>
        </div>
      </div>
    </div>
  </div>
</div>

Upvotes: 0

Views: 257

Answers (1)

joh04667
joh04667

Reputation: 7427

It's good you're thinking about this. There are three approaches that you can take:

The first is ngSwitch. If ngIf is the JS if() statement, ngSwitch is the switch ... case statement. Fairly self-explanatory.

The next is a dynamic component loader. This is a component that can take some sort of @Input and dynamically render a different component inside itself based on some criterion. You'll need a component for the logic, a TemplateRef in that component (usually from a directive) to attach the rendered component to, and some services injected. Here's a great guide on how to do that. I highly recommend exploring dynamic component loading, even if it isn't the right solution, because it gives a lot of insight into how Angular works behind the scenes.

The third depends on your setup. To me, it seems like conditionally displaying components based on a condition that can only be true once in the conditional set is essentially accomplishing what the Router should do. Instead of binding to all those statements, why not just make a route for each one? That way you could have each possible display value as a route that is reusable. The router is hierarchal, so you can have multiple <router-outlet>s in a parent-child relationship. You can also have multiple named outlets in the same template. You can even pass context to each route.

Upvotes: 1

Related Questions