How to influence child's viewed content sequence in Angular?

Viewed 76

I have a reusable section that based on parent's input creates some paragraphs in the DOM. It was working just fine, till the requirements had me take the paragraphs' sequence into account. I solved it the most obvious way and moved on...

My solution involved ngIf, ngSwitch could've been used likewise:

parent template

<button (click)="orderisBADC()">Order BADC</button>
<button (click)="orderisBDCA()">Order BDCA</button>
<button (click)="orderisCBDA()">Order CBDA</button>
<app-child [order]="order"></app-child>

parent component

export class HomeComponent {
  order = '';
  orderisBADC() {
    this.order = 'BADC';
  }
  orderisBDCA() {
    this.order = 'BDCA';
  }
  orderisCBDA() {
    this.order = 'CBDA';
  }
}

child template

<div *ngIf="order === 'BADC'">
    <p>B</p>
    <p>A</p>
    <p>D</p>
    <p>C</p>
</div>
<div *ngIf="order === 'BDCA'">
    <p>B</p>
    <p>D</p>
    <p>C</p>
    <p>A</p>
</div>
<div *ngIf="order === 'CBDA'">
    <p>C</p>
    <p>B</p>
    <p>D</p>
    <p>A</p>    
</div>

child component

export class ChildComponent implements OnInit {
  @Input()
  order: string;
}

But I could easily imagine there will be more possible sequences in the future. Is there a smarter way to overcome this, provided that the paragraphs are not enough of an entity themself to be even considered a separate component? Thank you in advance for any suggestions. :)

Edit:

I would like to clarify something.

The A, B, C, D texts are just placeholders. For simplification let's assume that the content we have in child is separated into equivalent block elements but their interior may vary. Some may have inputs, other tables and eventually some are filled with text, but it's in no way equal to the sequence symbols. Only child decides what's inside each element. The question remains the same: how to influence only sequence and/or existance of a viewed content from parent to child?

2 Answers

How about

in component:

orders = ['BADC', 'BDCA', 'CBDA'];

In template:

<button *ngFor="let order of orders" (click)="setOrder(order )">Order {{order}}</button>
<app-child [order]="order"></app-child>

Child template:

<div>
  <p *ngFor="let item of order">{{ item }}</p>
</div>

Given your example, it would probably make more sense to prepare the data in your parent component and pass it then as is to your child:

export class HomeComponent {
  items = ['B', 'D', 'C' , 'A']; // default order

  orderIsBADC() {
    this.items = ['B', 'A', 'D' , 'C'];
  }
  orderIsBDCA() {
    this.items = ['B', 'D', 'C' , 'A'];
  }
  orderIsCBDA() {
    this.items = ['C', 'B', 'D' , 'A'];
  }
}

In your template you pass it as before:

<app-child [items]="items"></app-child>

Then you can simply iterate in your child component over the given object:

<div *ngIf="items">
    <p *ngFor="let items of items">{{ item }}</p>
</div>

This way you will be able to process also more complicated objects in your parent component and use functions to sort them, if you have an array for example you could use the following function to sort it alphabetically:

sortData(array: Array<number | string>): Array<number | string> {
    return array.sort((a, b) => a < b ? -1 : 1);
}
Related