IsraGab
IsraGab

Reputation: 5185

Conditional rendering in angular

In all my components I have 3 differents templates according to the data state: Show loader if data is loading Show error message if there is an error when fetching data. Show 'no data' if there is no data Otherwise show the component itself

For now I have a switch case in all of my components. I would like to move that logic in one place in order to keep my code as DRY as possible.

What would be the angular way to do it?

Upvotes: 1

Views: 677

Answers (1)

You can achieve that by using a structural directive, that looks like so

Here is a working stackblitz

@Directive({
  selector: '[appDeafultView]'
})
export class DeafultViewDirective implements OnInit, OnDestroy {
  @Input() appDeafultView: Observable<string>;
  stateSub;

  factoryMap = {
    error: () => {
      const factory2 = this.resolver.resolveComponentFactory(ErrorComponet);
      this.viewContainer.createComponent(factory2);
    },
    loading: () => {
      const factory = this.resolver.resolveComponentFactory(LoadingComponent);
      this.viewContainer.createComponent(factory);
    },
    loaded: () => {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  };

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private resolver: ComponentFactoryResolver
  ) {}

  ngOnInit() {
    this.stateSub = this.appDeafultView.subscribe(state => {
      console.log(state);
      this.viewContainer.clear();
      this.factoryMap[state]();
    });
  }

  ngOnDestroy() {
    this.stateSub.unsubscribe();
  }
}

My idea is that based on observable, describing the state of request you can show different templates, where the ErrorComponent and LoadingComponent are predefined and in the case your data has been loaded successfully you will show the element on which you have attached your directive.

The usage of this directive will look like so

<p *appDeafultView="mix$">
  Content loaded
</p>

Where mix$ will be an observable that will resolve as either loading, error or loaded, and based on that the appropriate thing will be rendered.

Upvotes: 3

Related Questions