vorillaz
vorillaz

Reputation: 6266

Angular.js, Masonry and jQueryUi sortable

I am trying to create a really simple Angular app, mixing up Masonry and a way to sort my appended elements. I have seen many many examples using jQueryUi as: http://jsfiddle.net/dj_straycat/Q5FWt/3/ and also a directive approach http://passy.github.io/angular-masonry/

Although I tried lots passed all the examples it doesn't seem to work well. The goal of my app is to create a list adding app with sortable option. I have followed Masonry's creator example as seen in: http://jsfiddle.net/desandro/XMfwZ/1/

My full Javascript code:

var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {

    $scope.t = $('#masonry');

    $scope.t.masonry({
        itemSelector:        '.layout-card',
        isResizable:        true,
        columnWidth: 150
    })

    $scope.t.sortable({
        distance: 12,
        forcePlaceholderSize: true,
        items: '.layout-card',
        placeholder: 'card-sortable-placeholder layout-card',
        tolerance: 'pointer',

        start:  function(event, ui) {            
                 console.log(ui); 
            ui.item.addClass('dragging').removeClass('layout-card');
            if ( ui.item.hasClass('bigun') ) {
                 ui.placeholder.addClass('bigun');
                 }
                   ui.item.parent().masonry('reload')
                },
        change: function(event, ui) {
                   ui.item.parent().masonry('reload');
                },
        stop:   function(event, ui) { 
                   ui.item.removeClass('dragging').addClass('layout-card');
                   ui.item.parent().masonry('reload');
        }
   });

    $scope.toBeRepeated = [{
        id: 1,
        content: 'Blah'
    }];

    var i = 2;

    $scope.prepend = function() {
        $scope.toBeRepeated.unshift({
            id: i,
            content: 'Blah' + i
        });
        i = i - 1;
    };

    $scope.add = function() {

        $scope.toBeRepeated.push({
            id: i,
            content: 'Blah' + i
        });
        i = i + 1;

    };

    $scope.addMultipleItems = function() {
        var arrayToPush = [];
        for (var j = 10; j <= 20; j++) {
            arrayToPush.push({
                id: j,
                content: 'Blah' + j
            });
        }
        $scope.toBeRepeated = $scope.toBeRepeated.concat(arrayToPush);
    }

    $scope.remove = function(item) {
        var id = $scope.toBeRepeated.indexOf(item);
        if (id != -1) {
            $scope.toBeRepeated.splice(id, 1);
        }
    };

    $scope.reload = function() {
        $scope.toBeRepeated = [{
            id: 1,
            content: 'Blah blah'
        }, {
            id: 2,
            content: 'Blah blah2'
        }];
        $scope.toBeRepeated = $scope.toBeRepeated.concat([{
            id: 3,
            content: 'blah3'
        }]);
    }

});

As well as a full working demo:http://plnkr.co/edit/TWo6r94IA6hjLQdwE3h3 . Although the sortable option works great there seem to be problems removing the elements as well as prepending and appending new elements. Thanks in advance.

Upvotes: 0

Views: 857

Answers (1)

Anthony Chu
Anthony Chu

Reputation: 37520

Masonry isn't being notified when Angular makes changes to the DOM. Add a function like this...

function reloadMasonry() {
    return $timeout(function() {
        $('#masonry').masonry('reload');
    });
}

And call it after any changes the list. For example:

$scope.prepend = function() {
    $scope.toBeRepeated.unshift({
        id: i,
        content: 'Blah' + i
    });
    i = i - 1;
    reloadMasonry();
};

Updated Plunker

Once you get it working, look into getting this into a directive instead of having all this DOM manipulation in the controller.

Upvotes: 1

Related Questions