Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hardcoded references to templateSources.anonymousTemplate prevent a pluggable template mechanism #2523

Open
karimayachi opened this issue Apr 8, 2020 · 0 comments

Comments

@karimayachi
Copy link
Contributor

karimayachi commented Apr 8, 2020

Hi,

After some more investigating regarding #2500 I decided to create a new TemplateSource that keeps it's stored Nodes away from the DOM. I used a WeakMap approach and this works and solves the problem mentioned in #2500.

However, I'm having a difficult time figuring out how to use or distribute this TemplateSource without having to patch Knockout itself.

It seems to me that the TemplateSource was meant to be a pluggable system, because it is documented and instructs you to implement a specific interface (with text(), data() and node() methods). This to me indicates that you should be able create a in-place-replacement for the default source.

It's being called from the nativeTemplateEngine, so the documentation mentions that you should also create a new template engine. From the comments:

// Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
// using and overriding "makeTemplateSource" to return an instance of your custom template source.

Ok, no big deal. So I made a new template engine as well to use the new template source.

But this is where the problems start:
makeTemplateSource in the templateEngine is only called on retrieval. Setting the template occurs in the template-binding, with a hardcoded dependency on the build-in tempate source.

new ko.templateSources.anonymousTemplate(element)['nodes'](container);

if (templateNodes.length > 0) {
var container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
new ko.templateSources.anonymousTemplate(element)['nodes'](container);
} else {

So, using the template-binding (and with that the foreach-binding) with a custom template source is out. Creating a altered version of the template-binding is also not an option, because it uses a couple of private functions, so you'd have to completely write a custom template binding with the same functionality, without using the private functions.

Even if this was a feasible option: the foreach-binding injects the nativeTemplateEngine back into the template-binding:

return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };

So, you'd be back to square one, unless you overwrite the foreach-binding as well.

I'm puzzled. Although it seems that it should be easy to create in-place-replacements for the template sources, you can't actually do so without patching Knockout.

My main question is: am I missing something? What am I doing wrong in order to just create a custom template source to use with the template-binding and the foreach-binding?

As a proof of concept I patched Knockout to have a default source that can be overwritten

    ko.templateSources.defaultSource = ko.templateSources.anonymousTemplate;
    ko.exportSymbol('templateSources.defaultSource', ko.templateSources.defaultSource);

and I've replaced the hardcoded calls to anonymousTemplate with calls to defaultSource. This works, although to really be a solution, we would also have to handle the fact that the nativeTemplateEngine uses both anonymousTemplate and domElement sources simultaneously.

Please advice......
Thanks and regards,
Karim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant