I have come across several situations in which I have to code my template call like this:
<!-- ko template: {name: 'paginatedList',
data: {listContainer: paginatedResults, itemTemplate: $parent.template}} -->
<!-- /ko -->
because in addition to my data object (e.g., paginatedResults
), I need to pass in supplemental information such as the name of the template to use in rendering items. As another example, when rendering an item in a list, I might need to know the current settings of a filter that is stored in some context logically far-removed from the item in a list.
Rather than having to contort my data model (in the above example, replacing paginatedResults
with {listContainer: paginatedResults, itemTemplate: $parent.template}}
, it would be nice to have a bit of syntax on templates that allows me to pass around (and acccrue as templates are evaluated hierarchically) some extra context that a deeply-nested template might need when rendering itself.
I guess what I wondering about is the feasibility of adding an extra (optional) parameter to the ko.bindingHandlers
functions (init
and update
) to make them look like this:
function (element,
valueAccessor,
allBindingsAccessor,
viewModel,
bindingContext,
context)
When coding the above example, I ought to be able to say something like
<!-- ko template: {name: 'paginatedList',
data: paginatedResults,
context: {itemTemplate: $parent.template}} -->
<!-- /ko -->
or better yet,
<!-- ko template: {name: 'paginatedList',
data: paginatedResults,
itemTemplate: $parent.template} -->
<!-- /ko -->
and have itemTemplate
become a variable I can refer to in nested templates and data-bind
attributes.
Does this make sense? I don't have a good understanding of how hard this would be to implement. I guess one thing to worry about are name collisions, but some naming conventions might circumvent that.
Gene
Without changes to Knockout core, I think that the best that you could do is a wrapper binding that creates a structure similar to what you currently are passing.
Binding might look like:
ko.bindingHandlers.templateWithContext = {
init: ko.bindingHandlers.template.init,
update: function(element, valueAccessor, allBindings, data, context) {
var options = ko.utils.unwrapObservable(valueAccessor());
ko.utils.extend(context, options.context);
return ko.bindingHandlers.template.update.apply(this, arguments);
}
};
You would call it like:
<div data-bind="templateWithContext: { name: 'itemsTmpl', data: items, context: { title: 'First' } }"></div>
Here is a sample: http://jsfiddle.net/rniemeyer/QNvFn/
It looks like you are using native templates, but if you are using jQuery Templates still, then it did include a templateOptions
feature that used the options
feature of jQuery Templates to pass context data. This is not available in the native templates. The general recommendation now is to use the $root
, $parent
, and $parents
variables to access the information or to pass an object as data
in the way that you described in your post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With