flex-layout icon indicating copy to clipboard operation
flex-layout copied to clipboard

<ng-content> applies wrong layout

Open phil294 opened this issue 6 years ago • 10 comments

<sub-app>
    <div fxFlex="30" style="background-color:lightgreen;"></div>
</sub-app>

with sub-app template being

<div fxLayout="column" style="height:100px; width:100px; background-color:lightgrey;">
    <ng-content></ng-content>
</div>

According to Chrome inspection, this results in: (omitted unimportant styles)

<sub-app>
   <div fxlayout="column">
      <div fxflex="30" style="max-width:30%;"></div>
   </div>
</sub-app>

wronglayout

However, the applied max-width:30%; is wrong, this should be max-height:30% since the layout direction is column.

Here is a plunker: https://plnkr.co/edit/wOzPHMFLSmXHtg1sKjHe?p=preview

phil294 avatar Aug 17 '17 10:08 phil294

@phil294 - this is a good bug find!

Issue

The projected content has FlexDirective which instantiates & performs its ngOnInit() before the LayoutDirective (hosted on the parent of the projected content area) instantiates and runs ngOnInit().

Solution

FlexDirective needs to update itself AFTER the content projection finishes. I think the only way to do that currently is for the LayoutDirective to query for content children after content init.

This is not ideal, however, as this significantly complicates LayoutDirective with couplings to 5-10 other classes.

What would be better is a life-cycle hook that informs the projected content itself that the projection has completed. @vicb - Is there any way to achieve this currently ?

ThomasBurleson avatar Aug 17 '17 11:08 ThomasBurleson

Does this also apply to ng-template?

mackelito avatar Aug 17 '17 14:08 mackelito

@mackelito If we are talking about nesting inside the same component (contrary to ng-content, which is used for displaying contents from the parent component), then no, this does not apply to ng-template and also not to ng-container. It works as expected. You can check here if you like

phil294 avatar Aug 17 '17 15:08 phil294

This issue [here] reveals an instantiation and life-cycle issue between dependent components when used with content projection.

ThomasBurleson avatar Aug 17 '17 15:08 ThomasBurleson

we also have the issue when we try to use <ng-container [ngTemplateOutlet]="step.content"></ng-container> the step.content template using flex-layout properties is not interpreted

is it going to be fixed in flex-layout ?

djtahl avatar Mar 16 '18 14:03 djtahl

This is blocked on functionality in Angular core, and won't be fixed in Flex Layout until it's fixed there.

CaerusKaru avatar Mar 16 '18 17:03 CaerusKaru

I experienced this hard to track down problem too. Its still a thing on Angular 8 + Flex-Layout 8.beta.26. I have created a repro on stackblitz https://stackblitz.com/edit/angular-adpowi

Btw. It works when using @angular/[email protected] and breaks with 20+

philipooo avatar Jul 24 '19 07:07 philipooo

Is this issue still blocked?

michaelfaith avatar Jul 21 '20 21:07 michaelfaith

I was experiencing similar issue, At least to me, It looks like the projected content applies the default flexLayout value "row" because it can not check the flexLayout in the ng-content wrapper.

I post this because at least in my concrete case i have a valid workaround by wrapping the projected content into an extra wrapper which is also projected.

That even makes sense if I have to project the same content in multiple places with different layouting.

<div style="height:100px; width:100px; background-color:lightgrey;">
    <ng-content></ng-content>
</div>
<sub-app>
   <div fxLayout="column" >
        <div fxFlex="30" style="background-color:lightgreen;"></div>
   </div>
</sub-app>

angelfraga avatar Oct 12 '20 10:10 angelfraga

That workaround might be ok for two components you're creating yourself. But if you're building reusable components and want to build the layout behavior into the component, that approach isn't really a great option.

michaelfaith avatar Dec 09 '20 01:12 michaelfaith