From a04d67500ef4fa6b56010c08ac3b8dd64e0663b8 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Mon, 19 Jan 2015 22:29:12 -0500 Subject: [PATCH] #420 allow unloading of modules --- docs/mithril.module.md | 8 +++++++- mithril.js | 7 ++++--- tests/mithril-tests.js | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/docs/mithril.module.md b/docs/mithril.module.md index a9f4efc8..6c5a3d8e 100644 --- a/docs/mithril.module.md +++ b/docs/mithril.module.md @@ -118,6 +118,12 @@ module1.controller = function() { } ``` +To unload a module without loading another module, you can simply call `m.module` without a module parameter: + +```javascript +m.module(rootElement, null); +``` + --- ### Signature @@ -145,7 +151,7 @@ where: Once the controller code finishes executing (and this may include waiting for AJAX requests to complete), the view class is instantiated, and the instance of the controller is passed as an argument to the view's constructor. - Note that controllers can manually instantiate child controllers (since they are simply Javascript constructors), and likewise, views can instantiate child views and manually pass the child controller instances down the the child view constructors. You should avoid instantiating controllers from views, since views can be rendered many times across the lifecycle of a page, and a redraw might wipe out sub-controller data, if it houses any. + Note that controllers can manually instantiate child controllers (since they are simply Javascript constructors), and likewise, views can call child views and manually pass the child controller instances down the the child view constructors. You should avoid instantiating controllers from views, since views can be rendered many times across the lifecycle of a page, and a redraw might wipe out sub-controller data, if it houses any. This "[turtles all the way down](https://en.wikipedia.org/wiki/Turtles_all_the_way_down)" approach is the heart of Mithril's component system. diff --git a/mithril.js b/mithril.js index 961b6746..ca005511 100644 --- a/mithril.js +++ b/mithril.js @@ -508,8 +508,8 @@ var m = (function app(window, undefined) { m.redraw.strategy("all"); m.startComputation(); roots[index] = root; - var currentModule = topModule = module; - var controller = new module.controller; + var currentModule = topModule = module = module || {}; + var controller = new (module.controller || function() {}); //controllers may call m.module recursively (via m.route redirects, for example) //this conditional ensures only the last recursive m.module call is applied if (currentModule === topModule) { @@ -537,11 +537,12 @@ var m = (function app(window, undefined) { } }; m.redraw.strategy = m.prop(); + var blank = function() {return ""} function redraw() { var forceRedraw = m.redraw.strategy() === "all"; for (var i = 0, root; root = roots[i]; i++) { if (controllers[i]) { - m.render(root, modules[i].view(controllers[i]), forceRedraw) + m.render(root, (modules[i].view || blank)(controllers[i]), forceRedraw) } } //after rendering within a routed context, we need to scroll back to the top, and fetch the document title for history.pushState diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 345670aa..9fa41460 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -55,6 +55,29 @@ function testMithril(mock) { return (root1.childNodes[0].nodeValue === "test1" && root2.childNodes[0].nodeValue === "test2") && (mod1.value && mod1.value === "test1") && (mod2.value && mod2.value === "test2") }) + test(function() { + mock.requestAnimationFrame.$resolve() + + var root = mock.document.createElement("div") + var unloaded = false + var mod = m.module(root, { + controller: function() { + this.value = "test1" + this.onunload = function() { + unloaded = true + } + }, + view: function(ctrl) {return ctrl.value} + }) + + mock.requestAnimationFrame.$resolve() + + m.module(root, null) + + mock.requestAnimationFrame.$resolve() + + return unloaded + }) //m.withAttr test(function() {