Skip to content

Commit

Permalink
Fix afterRender not firing issue with moving from empty template name…
Browse files Browse the repository at this point in the history
… to a valid template
  • Loading branch information
rniemeyer committed Nov 23, 2014
1 parent 7032e20 commit 2cd71fc
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 7 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "knockout-amd-helpers",
"version": "0.7.2",
"version": "0.7.3",
"main": "build/knockout-amd-helpers.min.js",
"ignore": [
"examples",
Expand Down
12 changes: 10 additions & 2 deletions build/knockout-amd-helpers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// knockout-amd-helpers 0.7.2 | (c) 2014 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
// knockout-amd-helpers 0.7.3 | (c) 2014 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
define(["knockout"], function(ko) {

//helper functions to support the binding and template engine (whole lib is wrapped in an IIFE)
Expand Down Expand Up @@ -207,7 +207,7 @@ if (ko.virtualElements) {
engine.makeTemplateSource = function(template, doc) {
var el;

//if a name is specified, then use the
//if a name is specified
if (typeof template === "string") {
//if there is an element with this id and it is a script tag, then use it
el = (doc || document).getElementById(template);
Expand Down Expand Up @@ -236,6 +236,11 @@ if (ko.virtualElements) {
existingAfterRender = options && options.afterRender,
localTemplate = options && options.templateProperty && bindingContext.$module && bindingContext.$module[options.templateProperty];

//restore the original afterRender, if necessary
if (existingAfterRender) {
existingAfterRender = options.afterRender = options.afterRender.original || options.afterRender;
}

//if a module is being loaded, and that module has the template property (of type `string` or `function`) - use that as the source of the template.
if (localTemplate && (typeof localTemplate === "function" || typeof localTemplate === "string")) {
templateSource = {
Expand All @@ -255,6 +260,9 @@ if (ko.virtualElements) {
existingAfterRender.apply(this, arguments);
}
};

//keep track of the original, so we don't double-wrap the function when template name changes
options.afterRender.original = existingAfterRender;
}

return engine.renderTemplateSource(templateSource, bindingContext, options);
Expand Down
4 changes: 2 additions & 2 deletions build/knockout-amd-helpers.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "knockout-amd-helpers",
"version": "0.7.2",
"version": "0.7.3",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-uglify": "~0.2.0",
Expand Down
19 changes: 19 additions & 0 deletions spec/amdTemplateEngine.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,25 @@ define(["knockout", "knockout-amd-helpers"], function(ko) {
});
});

it("should call the afterRender function, even if the initial template was empty", function(done) {
var vm = {
templateName: ko.observable(""),
first: ko.observable("Jon"),
last: ko.observable("Black"),
rendered: jasmine.createSpy()
};

applyBindings("template: { name: templateName, afterRender: rendered }", vm, null, function() {
vm.templateName("fresh");

setTimeout(function() {
expect(container.innerText).toEqual("fresh: Jon Black");
expect(vm.rendered.calls.count()).toEqual(1);
done();
}, 50);
});
});

it("should still first use a template in a script tag", function(done) {
var template = document.createElement("script");
template.type = "text/html";
Expand Down
10 changes: 9 additions & 1 deletion src/amdTemplateEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
engine.makeTemplateSource = function(template, doc) {
var el;

//if a name is specified, then use the
//if a name is specified
if (typeof template === "string") {
//if there is an element with this id and it is a script tag, then use it
el = (doc || document).getElementById(template);
Expand Down Expand Up @@ -71,6 +71,11 @@
existingAfterRender = options && options.afterRender,
localTemplate = options && options.templateProperty && bindingContext.$module && bindingContext.$module[options.templateProperty];

//restore the original afterRender, if necessary
if (existingAfterRender) {
existingAfterRender = options.afterRender = options.afterRender.original || options.afterRender;
}

//if a module is being loaded, and that module has the template property (of type `string` or `function`) - use that as the source of the template.
if (localTemplate && (typeof localTemplate === "function" || typeof localTemplate === "string")) {
templateSource = {
Expand All @@ -90,6 +95,9 @@
existingAfterRender.apply(this, arguments);
}
};

//keep track of the original, so we don't double-wrap the function when template name changes
options.afterRender.original = existingAfterRender;
}

return engine.renderTemplateSource(templateSource, bindingContext, options);
Expand Down

0 comments on commit 2cd71fc

Please sign in to comment.