I am having problems in bind a Knockout array with Material Design Lite checkbox. Basically it doesn't show the checkbox checked.
How can that be fixed?
var ViewModel = function() {
this.uniqueTabsNames = ko.observableArray(['one', 'two', 'three']);
}
ko.applyBindings(new ViewModel());
<link href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/material-design-lite/1.3.0/material.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/material-design-lite/1.3.0/material.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<main class="mdl-layout__content">
<div class="page-content">
<p><b>generated via KO, it doesn't work</b></p>
<!-- ko foreach: uniqueTabsNames -->
<div class="nav-checkbox-item">
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" data-bind="attr: {'for': $data}">
<input data-bind="attr: {'id': $data}" type="checkbox" class="mdl-checkbox__input"/>
<span class="mdl-checkbox__label" data-bind="text: $data"></span>
</label>
</div>
<!-- /ko -->
<p><b>non KO checkbox</b></p>
<div class="nav-checkbox-item">
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for='testbox'>
<input id='testbox' type="checkbox" class="mdl-checkbox__input" />
<span class="mdl-checkbox__label">test box</span>
</label>
</div>
</div>
</main>
</div>
The problem here is that material design runs a function on page load to bind event handlers and functionality to certain DOM elements (like the checkbox in your case).
Because knockout essentially needs to run (or will redraw when dependencies change) the elements you bind functionality to. In your case, the foreach
can/will only run after knockout has been intialized, which is typically done on DOM ready. Hence, Material won't have had access to that element when it runs it's bindings initially.
You need to have a Custom Binding
to run the Material "logic" on the readiness of the element. The process is dead simple.
Pseudo-code:
- Create a custom binding called whatever you'd like.
- In the custom binding
init
method, pass theelement
knockout gives you into the Material function that will attach the required event handlers.
Hopefully that helps you!
EDIT: From the Material Design lite webpage
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function.
Knowing this, in your Custom Binding you need to pass the element
knockout gives you, to the aforementioned handler, like: componentHandler.upgradeElement(element)
EDIT EDIT: The code
ko.bindingHandlers.SomeBinding = {
init: function(element) {
if(!(typeof(componentHandler) == 'undefined')){
componentHandler.upgradeElement(element);
}
}
};
来源:https://stackoverflow.com/questions/44208015/how-to-bind-knockout-checkbox-to-a-material-design-lite