diff --git a/mithril.js b/mithril.js index f036d7e8..4343068e 100644 --- a/mithril.js +++ b/mithril.js @@ -234,7 +234,8 @@ var m = (function app(window, undefined) { else if (data != null && dataType === OBJECT) { if (data.view) { var module = data, onunload - var controller = cached.controller || new (module.controller || function() {}) + var controllerConstructor = module.controller.$original || module.controller + var controller = controllerConstructor === cached.controllerConstructor ? cached.controller : new (module.controller || function() {}) data = pendingRequests == 0 ? module.view(controller) : {tag: "placeholder"} if (controller.onunload) unloaders.push({controller: controller, handler: controller.onunload}) if (!data.tag) throw new Error("Component template must return a virtual element, not an array, string, etc.") @@ -270,6 +271,7 @@ var m = (function app(window, undefined) { nodes: [node] }; if (controller) { + cached.controllerConstructor = controllerConstructor cached.controller = controller if (controller.onunload && controller.onunload.$old) controller.onunload = controller.onunload.$old if (pendingRequests && controller.onunload) { @@ -289,6 +291,10 @@ var m = (function app(window, undefined) { if (hasKeys) setAttributes(node, data.tag, data.attrs, cached.attrs, namespace); cached.children = build(node, data.tag, undefined, undefined, data.children, cached.children, false, 0, data.attrs.contenteditable ? node : editable, namespace, configs); cached.nodes.intact = true; + if (controller) { + cached.controllerConstructor = controllerConstructor + cached.controller = controller + } if (shouldReattach === true && node != null) parentElement.insertBefore(node, parentElement.childNodes[index] || null) } //schedule configs to be called. They are called after `build` finishes running @@ -527,6 +533,7 @@ var m = (function app(window, undefined) { if (args[0] && args[0].key != null) template.attrs.key = args[0].key return template } + controller.$original = module.controller var output = {controller: controller, view: view} if (args[0] && args[0].key != null) output.attrs = {key: args[0].key} return output diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 7077d170..41447894 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -476,6 +476,51 @@ function testMithril(mock) { return count === 3 }) + test(function() { + // a route change should initialize a component's controller + mock.requestAnimationFrame.$resolve() + mock.location.search = "?" + + var root = mock.document.createElement("div") + var countA = 0 + var countB = 0 + var subA = { + controller: function(){ countA += 1 }, + view: function() { return m("div") } + } + var subB = { + controller: function() { countB += 1 }, + view: function() { return m("div") } + } + m.route(root, "/a", { + "/a": { + view: function () { + return m('.page-a', [ + m('h1'), m.module(subA, { x: 11 }) + ]) + } + }, + "/b": { + view: function() { + return m('.page-b', [ + m('h2'), m.module(subB, { y: 22 }) + ]) + } + } + }) + + mock.requestAnimationFrame.$resolve() + + m.route("/b") + + mock.requestAnimationFrame.$resolve() + + m.route("/a") + + mock.requestAnimationFrame.$resolve() + + return countA === 2 && countB === 1 + }) test(function() { var root = mock.document.createElement("div") var module = {}, unloaded = false