4

The issue works as follows. I have some code that actually works like this:

<content1>
    <mat-horizontal-stepper *ngIf="somevar" >
        <content2></content2>
    </mat-horizontal-stepper>
    <mat-vertical-stepper *ngIf="!somevar" >
        <content2></content2>
    </mat-vertical-stepper>
</content1>

I mean, content2 is always the same but mat-stepper is vertical or horizontal if somevar is true or false

How can i achieve this without copying the code of content2?

Posdata: I Can't create another component to hold the content of content2, since i need the variables that i'm using in content1 inside the stepper and i don't want to copy/paste code absolutely. It is only a thing of how i will render content depending on somevar.

2 Answers2

5

Typically, if you can't use a component, then you can use a template and containers to display the same content multiple times.

In the example below I replaced the container-2 elements with ng-container components. Elsewhere I added a ng-template component and placed container-2 into the content. Finally I associate the two by putting *ngTemplateOutlet directives on the containers and passing them a reference to the template using a template variable.

<content1>
  <mat-horizontal-stepper *ngIf="somevar" >
    <ng-container *ngTemplateOutlet="content2Template"></ng-container>
  </mat-horizontal-stepper>
  <mat-vertical-stepper *ngIf="!somevar" >
    <ng-container *ngTemplateOutlet="content2Template"></ng-container>
  </mat-vertical-stepper>
</content1>
<ng-template #content2Template>
  <content2></content2>
</ng-template>

However, this method won't work if you're using an angular material Stepper and Steps. The reason is because the Step components expect an ancestor Stepper component to be injected into it. Since you want to reuse the templates they have to be outsize of the Steppers so there is no way for you to meet that injection requirements. The method above won't work in any situation where the child component expects the parent to be injected.

The only other solution would be to use templates for the content themselves. So while the step components are repeated the forms inside of them will not. Presumably the forms will be the meat of the content so there won't be too much repetition.

<mat-vertical-stepper> *ngIf="somevar" 
  <mat-step label="Step 1" >
    <ng-container *ngTemplateOutlet="Content1"></ng-container>
  </mat-step>
  <mat-step label="Step 2">
    <ng-container *ngTemplateOutlet="Content2"></ng-container>
  </mat-step>
</mat-vertical-stepper>
<mat-horizontal-stepper>
  <ng-template #tmplt let-stepper *ngIf="!somevar">
    <mat-step label="Step 1" >
      <ng-container *ngTemplateOutlet="Content1"></ng-container>
    </mat-step>
    <mat-step label="Step 2">
      <ng-container *ngTemplateOutlet="Content2"></ng-container>
    </mat-step>
  </ng-template>    
  <ng-container *ngTemplateOutlet="tmplt"></ng-container>
</mat-horizontal-stepper>
<ng-template #Content1>Content1</ng-template>
<ng-template #Content2>Content2</ng-template>
Daniel Gimenez
  • 18,530
  • 3
  • 50
  • 70
  • This seems a properly answer but unfortunately not in this case, because of the mat-stepper it gives me an error if i try to set the content with the steps outside the matstepper declaration. – Cesar Leonardo Ochoa Contreras Oct 04 '18 at 19:06
  • 1
    I see that the problem is that matStep expects an ancestor stepper to be injected. I updated my answer with what seems to be the best compromise. It looks verbose but that's only because we've provided stubs for the content samples. – Daniel Gimenez Oct 04 '18 at 21:24
0

You could also write a new wrapper component for your steppers, which then branches over a property whether it is vertical or horizontal.

<mat-stepper [orientation]="somevar ? 'horizontal' : 'vertical'">
  <content2></content2>
</mat-stepper>

while mat-stepper looks like

<ng-container *ngIf="orientation === 'horizontal'; else vertical">
  <mat-horizontal-stepper>
    <ng-content>
  </mat-horizontal-stepper>
</ng-container>
<ng-template #vertical>
  <mat-vertical-stepper>
    <ng-content>
  </mat-vertical-stepper>
</ng-template>

this is especially a good solution if you run into this problem more often in your code than once

Patrick Kelleter
  • 2,631
  • 1
  • 13
  • 19