Search code examples
htmlcssangularangular-material2angular-flex-layout

Angular flex layout not applying to child component


I am trying to create a flex layout grid component of mat-cards in angular like so:

<div
  fxLayout.xs="column"
  fxLayout="row wrap"
  fxLayoutGap="10px"
  ngClass.gt-xs="ml-10"
>
  <app-card
    fxFlex.sm="0 1 calc(50%-10px)"
    fxFlex.md="0 1 calc(33%-10px)"
    fxFlex.gt-md="0 1 calc(25%-10px)"
    *ngFor="let cardModel of apodCards$ | async"
    [cardModel]="cardModel"
  >
  </app-card>
</div>

Which ends up looking like this : enter image description here

If I use the html template of my app-card component instead like so:

<div
  fxLayout.xs="column"
  fxLayout="row wrap"
  fxLayoutGap="10px"
  ngClass.gt-xs="ml-10"
>
  <mat-card
    fxFlex.sm="0 1 calc(50%-10px)"
    fxFlex.md="0 1 calc(33%-10px)"
    fxFlex.gt-md="0 1 calc(25%-10px)"
    *ngFor="let cardModel of apodCards$ | async"
    class="example-card"
  >
    <mat-card-header>
      <mat-card-title>{{ cardModel.title }}</mat-card-title>

      <mat-card-subtitle>{{ cardModel.subTitle }}</mat-card-subtitle>
    </mat-card-header>
    <img mat-card-image src="{{ cardModel.url }}" alt="Error Photo" />
    <ng-content></ng-content>

    <mat-card-content>
      <p [innerHTML]="cardModel.description"></p>
    </mat-card-content>

    <mat-card-actions>
      <app-share-button [url]="cardModel.shareUrl || ''"> </app-share-button>
    </mat-card-actions>
  </mat-card>
</div>

It ends up looking like this : enter image description here

How do I get my app-card component to look like the 2nd image?

I tried refactoring the app-card component like so:

<mat-card
  fxFlex.sm="0 1 calc(50%-10px)"
  fxFlex.md="0 1 calc(33%-10px)"
  fxFlex.gt-md="0 1 calc(25%-10px)"
  class="example-card"
>
  <mat-card-header>
    <mat-card-title>{{ cardModel.title }}</mat-card-title>

    <mat-card-subtitle>{{ cardModel.subTitle }}</mat-card-subtitle>
  </mat-card-header>
  <img mat-card-image src="{{ cardModel.url }}" alt="Error Photo" />
  <ng-content></ng-content>

  <mat-card-content>
    <p [innerHTML]="cardModel.description"></p>
  </mat-card-content>

  <mat-card-actions>
    <app-share-button [url]="cardModel.shareUrl || ''"> </app-share-button>
  </mat-card-actions>
</mat-card>

And then using in grid component like this:

<div
  fxLayout.xs="column"
  fxLayout="row wrap"
  fxLayoutGap="10px"
  ngClass.gt-xs="ml-10"
>
  <app-card
    *ngFor="let cardModel of apodCards$ | async"
    [cardModel]="cardModel"
  >
  </app-card>
</div>

With no luck.

Edit: See Stackblitz

<div fxLayout.xs="column" fxLayout="row wrap" fxLayoutGap="10px" ngClass.gt-xs="ml-10">
  <!-- This doesn't work, maybe I need to apply flex to the custom CardComponent somehow? -->
  <app-card fxFlex.sm="0 1 calc(50%-10px)" fxFlex.md="0 1 calc(33%-10px)" fxFlex.gt-md="0 1 calc(25%-10px)"
    *ngFor="let card of cards;" [card]="card">
  </app-card>

  <!-- This works -->
  <!-- <mat-card *ngFor="let card of cards;" fxFlex.sm="0 1 calc(50%-10px)" fxFlex.md="0 1 calc(33%-10px)"
    fxFlex.gt-md="0 1 calc(25%-10px)">
    <mat-card-title>{{card.name}}</mat-card-title>
    <img mat-card-image src="{{card.picture.uri}}" class="image">
    <mat-card-content>{{card.description}}</mat-card-content>
    <mat-card-actions>Container for buttons at the bottom of the card</mat-card-actions>
  </mat-card> -->

</div>

Solution

  • - Here's a solution with components : Add fxFlex to your card

    <div fxLayout.xs="column" fxLayout="row wrap" fxLayoutGap="10px" ngClass.gt-xs="ml-10">
      <app-card fxFlex.sm="0 1 calc(50%-10px)" fxFlex.md="0 1 calc(33%-10px)" fxFlex.gt-md="0 1 calc(25%-10px)"
        *ngFor="let card of cards;" [card]="card">
        <mat-card fxFlex>...</mat-card>
        <mat-card fxFlex>...</mat-card>
        <mat-card fxFlex>...</mat-card>...
      </app-card>
    </div>
    

    - Here's a solution without components :

    <div fxLayout.xs="column" fxLayout="row wrap" fxLayoutGap="10px" ngClass.gt-xs="ml-10">
      <mat-card fxFlex.sm="0 1 calc(50%-10px)" fxFlex.md="0 1 calc(33%-10px)" fxFlex.gt-md="0 1 calc(25%-10px)">
        <mat-card-title>Card 1</mat-card-title>
        <img mat-card-image src="https://kakiseni.org/wp-content/uploads/2018/03/250X250.png" class="image">
        <mat-card-content>Primary card content. Intended for blocks of text</mat-card-content>
        <mat-card-actions>Container for buttons at the bottom of the card</mat-card-actions>
      </mat-card>
    
      <mat-card>...</mat-card>
    </div>
    

    Stackblitz link

    enter image description here