Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Packery / Masonry to work with angular2

I'm trying to get Packery / Masonry to work on a component. Packery is detecting the container but giving it a height of zero suggesting the content hasn't loaded even though I'm using imagesLoaded. I've tried using various lifecycle hooks but they all have the same result so bit lost as to where I'm going wrong.

import {BlogService} from './blog.service';
import {Blog} from './blog.model';
import {Component, ElementRef, OnInit, AfterViewInit} from '@angular/core';
import {LinkyPipe} from '../pipes/linky.pipe';

declare var Packery: any;
declare var imagesLoaded: any;

@Component({
  moduleId: module.id,
  selector: 'blog',
  templateUrl: 'blog.component.html',
  providers: [BlogService],
  pipes: [LinkyPipe]
})

export class BlogComponent implements OnInit, AfterViewInit {
  blogs: Blog[];
  errorMessage: string;
  constructor(private _blogService: BlogService, public element: ElementRef) { }
  ngOnInit() {
    this.getBlogs();
  }

  ngAfterViewInit() {
    let elem = this.element.nativeElement.querySelector('.social-grid');
    let pckry;
    imagesLoaded(elem, function(instance) {
      console.log('loaded');
      pckry = new Packery(elem, {
        columnWidth: '.grid-sizer',
        gutter: '.gutter-sizer',
        percentPosition: true,
        itemSelector: '.social-card'
      });
    });
  }

  getBlogs() {
    this._blogService.getPosts()
      .subscribe(
      blogs => this.blogs = blogs,
      error => this.errorMessage = <any>error);
  }
}
like image 228
dottodot Avatar asked May 11 '16 10:05

dottodot


1 Answers

Ok I worked it out that I needed to use AfterViewChecked instead however when I first tried it ended up it a never ending loop as this is fired every time the DOM changes so as you'll see there are a few extra checks in place so it only fires once. Still not sure if it's the correct way to do it but it works for now.

import {BlogService} from './blog.service';
import {Blog} from './blog.model';
import {Component, ElementRef, OnInit, AfterViewChecked} from '@angular/core';
import {LinkyPipe} from '../pipes/linky.pipe';
declare var Packery: any;
declare var imagesLoaded: any;
@Component({
  moduleId: module.id,
  selector: 'coco-blog',
  templateUrl: 'blog.component.html',
  providers: [BlogService],
  pipes: [LinkyPipe]
})
export class BlogComponent implements OnInit, AfterViewChecked {
  blogs: Blog[];
  errorMessage: string;
  isGridInitialized: boolean;
  constructor(private _blogService: BlogService, public element: ElementRef) { }
  ngOnInit() {
    this.getBlogs();
  }
  ngAfterViewChecked() {
    if (this.blogs && this.blogs.length > 0 && !this.isGridInitialized) this.initGrid();
  }
  getBlogs() {
    this._blogService.getPosts()
      .subscribe(
      blogs => this.blogs = blogs,
      error => this.errorMessage = <any>error);
  }
  initGrid() {
    this.isGridInitialized = true;
    let elem = document.querySelector('.social-grid');
    let pckry;
    imagesLoaded(elem, function(instance) {
      console.log('all images are loaded');
      pckry = new Packery(elem, {
        percentPosition: true,
        itemSelector: '.social-card',
        gutter: 20
      });
    });
  }
}
like image 122
dottodot Avatar answered Nov 11 '22 18:11

dottodot