8

I need to sort components dynamically in the following template

<div class="orderList">
    <componentA></componentA>
    <componentB></componentB>
    <componentC></componentC>
</div>

by the object like

orders: {
    componentA: 2,
    componentB: 3,
    componentC: 1
}

So I expect to see componentC at first then componentA and finally componentB?

Notes: components are more than three

fingerpich
  • 8,500
  • 2
  • 22
  • 32
  • What not order them in your root component right away? Please give us more context. – Christopher Jul 24 '17 at 12:07
  • Do you wish to render them on certain order? – Drag13 Jul 24 '17 at 12:10
  • @Christopher after ordering I need, componentC comes at first and then componentA and then componentB – fingerpich Jul 24 '17 at 12:11
  • Use ng-repeat to render and rerender them – Drag13 Jul 24 '17 at 12:11
  • 1
    If you add components like demonstrated in https://stackoverflow.com/questions/36325212/angular-2-dynamic-tabs-with-user-click-chosen-components/36325468#36325468, then you just need to reorder the component types in an array. – Günter Zöchbauer Jul 25 '17 at 08:12
  • 1
    thank you @GünterZöchbauer. I have added an answer from your helpful comment. but I think there could be an easier answer to this simple question. – fingerpich Jul 25 '17 at 13:00
  • @GünterZöchbauer I think its better to use `css flex` for this issue because of better performance at least. how do you think? – fingerpich Jul 26 '17 at 07:00
  • @fingerpich I'd expect this to be complicated with CSS. If it's only 3 components and the order doesn't change, then I would just hardcode the order in HTML, if it's more components and the order does actually change, then I find it easiest to reorder an array and let `*ngFor` do the rest. I don't know a good way to sort for example 25+ elements with flex in arbitrary order, but CSS isn't my strong side ;-) – Günter Zöchbauer Jul 26 '17 at 07:11
  • Theoretically they could be sorted in CSS, but dynamically enabling them for the sake of lazy loading wouldn't be easy. – massic80 Oct 21 '22 at 09:05

2 Answers2

10

Using CSS flex order property

<div style="display:flex;">
   <componentA [style.order]="orders.componentA"></componentA>
   <componentB [style.order]="orders.componentB"></componentB>
   <componentC [style.order]="orders.componentC"></componentC>
</div>
fingerpich
  • 8,500
  • 2
  • 22
  • 32
  • I just want to add, that in order to change direction u can use ```display:flex; flex-direction: column;``` (By default child components are in a row) – Jake_3H May 09 '22 at 09:06
  • You have to be careful with accessibility with this one. Tabbing order has to be intuitive for users with visual disabilities. See more: https://stackoverflow.com/questions/44308934/flexbox-order-and-tabbing-navigation – mmokrzycki Nov 18 '22 at 10:01
1

As @GünterZöchbauer suggested in comments this answer uses ngComponentOutlet to sort components dynamically

<ng-container 
    *ngFor="item in sortedComponent" 
    *ngComponentOutlet="item.component">
</ng-container>

sortedComponent = [
    {index: 4, component: 'componentA'},
    {index: 5, component: 'componentB'},
    {index: 2, component: 'componentC'},
].sort((a, b) => a.index > b.index)
fingerpich
  • 8,500
  • 2
  • 22
  • 32
  • what is `component` in `item.component`? Is it a component directive? – WasiF Apr 03 '18 at 09:30
  • item.component is component name that you have defined it. – fingerpich Apr 03 '18 at 09:35
  • when you have created the component's object then why there is a need to again add component class name. This looks illogical – WasiF Apr 03 '18 at 09:39
  • let say you have a component class as `myComponent`, then how it would be called? According to you (what I understand) `item.myComponent`, right – WasiF Apr 03 '18 at 09:41
  • I just have updated the answer and add more details about what I did – fingerpich Apr 03 '18 at 13:32
  • @fingerpich to be clear, you cannot use strings as your component. You need to pass the type of the component. The actual usage of ngComponentOutlet is much more complex than this. This answer gives a better overview https://stackoverflow.com/questions/47522759/angular-4-using-ngcomponentoutlet-to-display-dynamically-changing-contentchildre – bryan60 Nov 14 '18 at 00:47
  • if you had defined those components it will work. see the [document](https://angular.io/api/common/NgComponentOutlet), I tested it and it worked. – fingerpich Nov 14 '18 at 00:56