Search code examples
angularangular-materialmasonry

Angular and NGX-Masonry - display issue


I wanted to integrate Masonry into an Angular application. I installed the ngx-masonry library.
The problem: When rendered, my page has a huge gap between the headline and the masonry-content. My expected behavior: Every card should start at the very top.

Screenshot with percentage width like it should be at the end (The first card is the grey box starting at the bottom)

Below that gap, the cards align as expected.

This is the code in my html file (simplified, in reality i have one item in width2 and 7 in the "normal" width. I hoped that this will suffice)

<div class="grid-container">
  <h1 class="mat-h1">Headline</h1>
  <ngx-masonry [options]="{itemSelector: '.masonry-item', columnWidth: '.grid-sizer', percentPosition: true }">

    <div class="grid-sizer"></div>

    <ngxMasonryItem class="masonry-item masonry-item--width2">
      <app-card id="card1" title="card 1 in full width">
        <app-card1> </app-card1>
      </app-card>
    </ngxMasonryItem>

    <ngxMasonryItem class="masonry-item">
      <app-card id="card2" title="card 2 with other width">
        <app-card2></app-card2>
      </app-card>
    </ngxMasonryItem>
</ngx-masonry>
<div>

Here is the code for that from my sass file:

.grid-sizer, 
.masonry-item {
  width: 50%;
}

.masonry-item--width2 {
  width: 100%;
}

The grid-container div around the masonry and headline tags does not have any custom styles.

I did not make any changes in the component.ts for masonry (only for other content related stuff, I am not allowed to share).

I tried to give all items a fix width and not do it with percent. My result with every item in 200px was pretty unsatisfying as well: Example with fix width

I could not find anything about a problem like that.

If this is important: I have angular-material included in the project as well.

Help is appreciated and if anything is unclear, I am glad to share more info.


Solution

  • I found a solution:

    With @ViewChild(NgxMasonryComponent) masonry: NgxMasonryComponent; you can access the masonry object and call the functions individually.

    And using this.masonry.reloadItems(); and this.masonry.layout(); You can "refresh" the layout and this worked for me like a charm.

    reloadMasonryLayout() {
        if (this.masonry !== undefined) {
          this.masonry.reloadItems();
          this.masonry.layout();
        }
      }
    

    I call this function in the ngOnInit and whenever the layout changes (due to card order)

    I found this solution in a demo on github