angular / flex-layout

Provides HTML UI layout for Angular applications; using Flexbox and a Responsive API
MIT License
5.9k stars 772 forks source link

<ng-content> applies wrong layout #381

Open phil294 opened 7 years ago

phil294 commented 7 years ago
<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

ThomasBurleson commented 7 years ago

@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 ?

mackelito commented 7 years ago

Does this also apply to ng-template?

phil294 commented 7 years ago

@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

ThomasBurleson commented 7 years ago

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

djtahl commented 6 years ago

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 ?

CaerusKaru commented 6 years ago

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

philipooo commented 5 years ago

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/flex-layout@7.0.0.beta.19 and breaks with 20+

michaelfaith commented 4 years ago

Is this issue still blocked?

angelfraga commented 4 years ago

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>
michaelfaith commented 3 years ago

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.