#481 recreate controller if only component type changes

This commit is contained in:
Leo Horie 2015-03-11 21:18:13 -04:00
parent 114ebec22f
commit fdbbe7f78f
2 changed files with 53 additions and 1 deletions

View file

@ -234,7 +234,8 @@ var m = (function app(window, undefined) {
else if (data != null && dataType === OBJECT) { else if (data != null && dataType === OBJECT) {
if (data.view) { if (data.view) {
var module = data, onunload 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"} data = pendingRequests == 0 ? module.view(controller) : {tag: "placeholder"}
if (controller.onunload) unloaders.push({controller: controller, handler: controller.onunload}) 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.") 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] nodes: [node]
}; };
if (controller) { if (controller) {
cached.controllerConstructor = controllerConstructor
cached.controller = controller cached.controller = controller
if (controller.onunload && controller.onunload.$old) controller.onunload = controller.onunload.$old if (controller.onunload && controller.onunload.$old) controller.onunload = controller.onunload.$old
if (pendingRequests && controller.onunload) { 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); 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.children = build(node, data.tag, undefined, undefined, data.children, cached.children, false, 0, data.attrs.contenteditable ? node : editable, namespace, configs);
cached.nodes.intact = true; cached.nodes.intact = true;
if (controller) {
cached.controllerConstructor = controllerConstructor
cached.controller = controller
}
if (shouldReattach === true && node != null) parentElement.insertBefore(node, parentElement.childNodes[index] || null) if (shouldReattach === true && node != null) parentElement.insertBefore(node, parentElement.childNodes[index] || null)
} }
//schedule configs to be called. They are called after `build` finishes running //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 if (args[0] && args[0].key != null) template.attrs.key = args[0].key
return template return template
} }
controller.$original = module.controller
var output = {controller: controller, view: view} var output = {controller: controller, view: view}
if (args[0] && args[0].key != null) output.attrs = {key: args[0].key} if (args[0] && args[0].key != null) output.attrs = {key: args[0].key}
return output return output

View file

@ -476,6 +476,51 @@ function testMithril(mock) {
return count === 3 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() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
var module = {}, unloaded = false var module = {}, unloaded = false