<div data-bind=”value: name, event: { focus: function() { viewModel.selectItem($data); }, blur: function() { viewModel.selectItem(null); }”></div>
The struggle for html-code purity is extensively discussed in this article - http://www.knockmeout.net/2011/08/simplifying-and-cleaning-up-views-in.html . You need to use dependentObservable, make custom-bindings, avoid anonymous functions. You can write your bindingProvider or use this https://github.com/rniemeyer/knockout-classBindingProvider . // <div data-bind="foreach: items"> // <li> <span data-bind="name"></span> <span data-bind="price"></span> </li> </div> // <div data-bind="template: {name:'person-template',data:person}"></div> <script type="text/html" id="person-template"> // <h3 data-bind="text: name"></h3> <p>Credits: <span data-bind="text: credits"></span></p> </script>
<div data-bind="with: currentState"> <div data-bind="template: {html:html,data:data}"></div> </div>
That is, if the html property is specified, then our stringTemplateEngine is called, otherwise we give it to the standard knockout. currentState is an object that must have html properties with html code and possibly data with a module object. ko.templateSources.stringTemplate = function(element,html) { this.domElement = element; this.html = ko.utils.unwrapObservable(html); } ko.templateSources.stringTemplate.prototype.text = function() { if (arguments.length == 0) return this.html; this.html = ko.utils.unwrapObservable(arguments[0]); }
var engine = new ko.nativeTemplateEngine(); // renderTemplate - makeTemplateSource engine.renderTemplate = function(template,bindingContext,options,templateDocument) { var templateSource = this.makeTemplateSource(template, templateDocument, bindingContext, options); return this.renderTemplateSource(templateSource, bindingContext, options); } // , 2 engine.makeTemplateSource = function(template, templateDocument, bindingContext, options) { // engine knockout- if (typeof template == "string") { templateDocument = templateDocument || document; var elem = templateDocument.getElementById(template); if (!elem) throw new Error("Cannot find template with ID " + template); return new ko.templateSources.domElement(elem); } // stringTemplateEngine, options else if (options && options.html) { return new ko.templateSources.stringTemplate(template,options.html); } else if ((template.nodeType == 1) || (template.nodeType == 8)) { // engine knockout- return new ko.templateSources.anonymousTemplate(template); } else throw new Error("Unknown template type: " + template); } ko.setTemplateEngine(engine);
define(["knockout","text"],function(ko) { return function(file,callback) { var s = this; s.callback = callback; s.data = ko.observable(null); s.html = ko.observable(null); require(["/js/modules/" + file + ".js","text!/js/templates/" + file + ".html"],function(Module,html) { s.data(typeof Module === "function" ? new Module(s) : Module); s.html(html); if (s.callback && typeof s.callback === "function") s.callback(s); }); s.setVar = function(i,v) { var data = s.data(); data[i] = v; s.data(data); } } });
<body> <div class="container" data-bind="template:{html:html,data:data}"></div> <script type="text/javascript" data-main="/js/main" src="/lib/require/require.js"></script> </body>
require(["knockout","state","stringTemplateEngine"], function(ko,State) { var sm = new State("app",function(state) { ko.applyBindings(state); }); });
// templates/app.html: <div class="row"> <div data-bind="with:menu"><div class="span3 menu" data-bind="template:{html:html,data:data}">Menu</div></div> <div data-bind="with:currentState"><div class="span9 content" data-bind="template:{html:html,data:data}"></div></div> </div>
// modules/app.js: define(["knockout","state"],function(ko,State) { return function() { var app = this; this.menu = new State("menu",function(state) { // , callback-, app, app state- state.setVar("app",app); }); this.currentState = ko.observable(null); } });
// menu.html <ul class="nav nav-list"> <li><a href="javascript:void(0);" data-bind="click:gotoSample" data-id="1">Hello World</a></li> <li><a href="javascript:void(0);" data-bind="click:gotoSample" data-id="2">Click counter</a></li> <li><a href="javascript:void(0);" data-bind="click:gotoSample" data-id="3">Simple list</a></li> ...
// menu.js: define(["jquery","knockout","state"],function($,ko,State) { return function() { var menu = this; this.gotoSample = function(obj,e) { var sampleId = $(e.target).attr("data-id"); var newState = new State("samples/sample" + sampleId,function(state) { state.setVar("app",menu.app); // app.currentState, .. observable- currentState, menu.app.currentState(state); }); } } });
Source: https://habr.com/ru/post/154003/
All Articles