javascript - Knockout calculate container height from custom element after rendering items -


i writing custom binding amongst other things, needs know height before running display logic. contents rendered in foreach binding.

normally, ko call binding init before of these items rendered, meaning height incorrect.

i used { controlsdescendantbindings: true } , manually bound child items before using height; works fine in init.

the problem is, i'd have binding fire update , recalculate height when items updated, , above pattern gives me you cannot apply bindings multiple times same element if change init update, understandably enough.

here cut down code:

html:

<a href="#" data-bind="click: rerun">re-run</a> <hr/> <div class="container" data-bind="test: true">     <!-- ko foreach: items -->         <div class="item" data-bind="text: id"></div>     <!-- /ko --> </div> <hr/> <b id="res"></b> 

css:

hr {     clear: both; }  .item {     width: 50px;     height: 50px;      background: red;     margin: 5px;     display: inline-block; } 

code:

ko.bindinghandlers.test = {     init:          function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)          {             var val = ko.unwrap(f_valueaccessor());              if(!!val)             {                    ko.applybindingstodescendants(bindingcontext, el);                  $('#res').html($(el).height());                  return { controlsdescendantbindings: true };             }         } };  function model(data, mapping) {     var _this = this;     var _mapping = $.extend({}, {}, mapping);      this.items = ko.observablearray();              if(data)         ko.mapping.fromjs(data, _mapping, _this);      this.rerun = function(model, e)     {         _this.items(_this.genitems());     }      this.genitems = function()     {                 var = [];          for(var = 0; < 10 + (math.random() * 20); i++)             a.push({id:i});          return a;     }      this.rerun(); }  var model = new model(); ko.applybindings(model); 

and fiddle: https://jsfiddle.net/whelkaholism/tzrxbojj/

i can see 2 ways solve this:

  1. pass object binding contains function reference can called model when items changed force recalculate (this works fine pretty clunky)

  2. use afterrender on foreach (this works fine also, adds code model)

the afterrender solution works fine , may turn out recommended method; mean have add model needs similar functionality, , custom binding seems nice abstraction.

is there (i.e. better #1) way of getting work using single custom binding on container?

the main thing missing in solution custom binding needs know items model in order subscribe changes , recalculate height of element. made height observable solution more knockout intended used.

my solution not require controlsdescendantbindings: true.

html:

<a href="#" data-bind="click: rerun">re-run</a> <hr/> <div class="container" data-bind="test: {heightvalue: containerheight, itemsmodel: items}">     <!-- ko foreach: items -->         <div class="item" data-bind="text: id"></div>     <!-- /ko --> </div> <hr/> <b id="res" data-bind="text: containerheight"></b> 

binding:

ko.bindinghandlers.test = {     init:          function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)          {             var data = f_valueaccessor();             var recalculate = function () {                 settimeout(function () {                     data.heightvalue($(el).height());                 }, 0);             }             data.itemsmodel.subscribe(function () {                 recalculate();             });              recalculate();         } }; 

the settimeout 0 helps fire height recalculation after rendering complete.

and view model same exception of added observable container height:

this.containerheight = ko.observable(); 

jsfiddle


Comments

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -