With custom binding for Masonry how would I resize the container appropriately

Posted by BigDubb on Stack Overflow See other posts from Stack Overflow or by BigDubb
Published on 2013-10-31T03:50:04Z Indexed on 2013/10/31 3:53 UTC
Read the original article Hit count: 153

Based on the suggestion give here, and the information given here on how to make a custom bindingHandler for a forEach, I decided to attempt to write my own custom binding for a forEach and Masonry.

Because the elements are added on the fly the redrawing and moving around of elements to fill the space doesn't occur. So, this functionality needed to be moved after the elements have been rendered or called after each item has been added.

Here is my bindingHandler

ko.bindingHandlers.masonry = {
init: function (element, valueAccessor, allBindingsAccessor) {
    var $element = $(element),
        originalContent = $element.html();
    $element.data("original-content", originalContent);
    //var msnry = new Masonry($element);
    return { controlsDescendantBindings: true }

},
update: function (element, valueAccessor, allBindingsAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor()),

    //get the list of items
    items = value.items(),

    //get a jQuery reference to the element
    $element = $(element),

    //get the current content of the element
    elementContent = $element.data("original-content");

    $element.html("");

    var container = $element[0];
    var msnry = new Masonry(container);

    for (var index = 0; index < items.length; index++) {
        (function () {
            //get the list of items
            var item = ko.utils.unwrapObservable(items[index]),
                $childElement = $(elementContent);

            ko.applyBindings(item, $childElement[0]);

            //add the child to the parent        
            $element.append($childElement);
            msnry.appended($childElement[0]);

        })();

        msnry.layout();
        msnry.bindResize();
    }
}

};

and the HTML implementing the handler.

<div id="criteriaContainer" data-bind="masonry: { items: SearchItems.Items }">
    <div class="searchCriterion control-group">
        <label class="control-label" data-bind="text: Description"></label>
        <div class="controls">
            <input type="hidden" data-bind="value: Value, select2: { minimumInputLength: 3, queryUri: SearchUri(), placeholder: Placeholder(), allowClear: true }" style="width: 450px">
        </div>
        <p data-bind="text: Value"></p>
    </div>
</div>

When this shows up on the page It stacks all if the elements rendered via the append method right on top of each other.

You can see in my bindingHandler I am calling bindResize as well as layout(), neither of which seem to be having any effect.

Here's a screenshot of what it looks like in the UI. Masonry example with Knockout

© Stack Overflow or respective owner

Related posts about knockout.js

Related posts about jquery-masonry