javascript - auto apply masonry in knockout binding handler after dynamic update -


i using knockoutjs masonry , have created custom knockout binding handler apply masonry html element.

the container want apply masonry has it's content injected dynamically using knockout's foreach binding.

the issue having getting masonry apply after masonry container has been updated dynamically.

in snippet example if click masonryize button destroy masonry container , reapply mansonry, how behaviour binding handler?

ko.bindinghandlers.masonry = {    update: function(element, valueaccessor) {      var options = valueaccessor();      $(element).masonry(options);    }    }    var vm = {    term: ko.observable(),    page: ko.observable(1),    per_page: ko.observable(3),    items: ko.observablearray(),    masonryize: function() {      $('.grid').masonry('destroy');      $('.grid').masonry({        itemselector: '.item',        columnwidth: 200      });    },    getstuff: function() {      $.ajax({        url: 'https://api.github.com/search/repositories',        method: 'get',        data: {          q: this.term,          page: this.page(),          per_page: this.per_page()        }      }).then(function(r) {        this.items(r.items)      }.bind(this))    }  }    ko.applybindings(vm);
.grid {    width: 400px;  }  .item {    margin-bottom: 2em;    border: 1px solid black;  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>  <script src="http://masonry.desandro.com/masonry.pkgd.js"></script>  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>      <div>    <label>term:</label>    <input type="text" data-bind="value: term" />  </div>  <div>    <label>page:</label>    <input type="text" data-bind="value: page" />  </div>  <div>    <label>no of items:</label>    <input type="text" data-bind="value: per_page" />  </div>    <div>    <button data-bind="click: getstuff">get stuff</button>    <button data-bind="click: masonryize">masonryize</button>  </div>    <div class="grid" data-bind="masonry: {itemselector: '.item', columnwidth: 200}, foreach: items">    <div class="item">      <p data-bind="text:name"></p>      <p data-bind="text:language"></p>    </div>  </div>

it depends on mean saying after masonsy container updated. mean resize or maybe loading new items? if know when container needs update can this:

ko.bindinghandlers.masonry = {     init: function(element, valueaccessor, allbindingsaccessor) {         ko.computed(function () {              var options = ko.unwrap(valueaccessor());               ko.unwrap(allbindingsaccessor().masonryupdater);               $(element).masonry('destroy');              $(element).masonry(options);         }, null, disposewhennodeisremoved: element);     } }  // ...  vm.masonryupdater = ko.observable();  // when need update run  vm.masonryupdater.valuehasmutated(); 

and apply binding so:

<div class="grid" data-bind="masonry: {itemselector: '.item', columnwidth: 200}, masonryupdater: masonryupdater, foreach: items">   <div class="item">     <p data-bind="text:name"></p>     <p data-bind="text:language"></p>   </div> </div> 

so happening here:

  1. we create subscription observable allbindingsaccessor().masonryupdater reading it. way whenever updates computed create reevaluate , reapply masonry.
  2. to tell knockout our observable has changed call vm.masonryupdater.valuehasmutated();
  3. the computed safely disposed after our grid element removed

this kind of looks voodoo, plus may exploiting side effects. maybe little. on plus side making things quite simple ourselves. needs done once executed outside computed, needs dependecy or update inside computed. easier debug , save data later use.

it described in detail here http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html


Comments

Popular posts from this blog

javascript - Karma not able to start PhantomJS on Windows - Error: spawn UNKNOWN -

Nuget pack csproj using nuspec -

c# - Display ASPX Popup control in RowDeleteing Event (ASPX Gridview) -