Search code examples
javascriptjqueryember.jsember-clijquery-masonry

Masonry is not a function in Ember Cli


How can i initiate a jQuery plugin in Ember-Cli?

I am trying to use Masonry plugin and this is the logic i want to implement

var $grid = $('.grid').masonry({
  itemSelector: '.grid-item',
  percentPosition: true,
  columnWidth: '.grid-sizer'
});
// layout Isotope after each image loads
$grid.imagesLoaded().progress( function() {
  $grid.masonry();
}); 

I am trying to use the event hook called didInsertElement, but the jQuery plugin does not initiate.

Here my code

import Ember from 'ember';

var PhotographyController = Ember.ObjectController.extend({
    didInsertElement : function(){
      this._super();
      Ember.run.scheduleOnce('afterRender', this, this.afterRenderEvent);
    },

    afterRenderEvent : function(){
      var $grid = $('.grid').masonry({
        itemSelector: '.grid-item',
        percentPosition: true,
        columnWidth: '.grid-sizer'
      });
      // layout Isotope after each image loads
      $grid.imagesLoaded().progress( function() {
        $grid.masonry();
      });  
    }
});

export default PhotographyController;

The console error "Masonry is not a function"

enter image description here

How can i initiate the Plugin and implement this logic?

I am using Ember 1.3.11


Solution

  • Apparently someone has already done something around Masonry as an ember addon.

    To try and answer your question, first off you must check if the Masonry file is included in your application. In ember-cli-build.js you should have something along the lines of:

    app.import('bower_components/mansonry/dist/masonry.min.js');
    

    Do notice that I made the path for that, you need to make sure the path is correct for your project. Here I'm assuming you would be using bower to manage dependencies. So you would need to have something like this in your bower.json file (and then run bower install).

    "masonry": "~3.3.2",
    

    If you want to use jQuery in an Ember component (which is what I think you need here). You should do the following:

    //components/masonry-component.js
    export default Ember.Component.extend({
      didInsertElement() {
       var $grid = this.$('.grid').masonry({
        itemSelector: '.grid-item',
        percentPosition: true,
        columnWidth: '.grid-sizer'
      });
       // layout Isotope after each image loads
       $grid.imagesLoaded().progress( function() {
         $grid.masonry();
       });  
      }
    });
    

    Notice the use of this.$('.grid') this means that your using a jquery selector which only starts searching for elements in the context of your component (so that you can have multiple components without interfering with each other). And in your component template the div with grid class:

    <div class='grid'>
      {{yield}}
    </div>
    

    And in your route template you would have:

    {{masonry-component}}