4

In a Durandal 2.x app I have a view that needs to fetch new data every time the user navigates to it. This view is served through a child router:

define(['plugins/router'], function(router) {
    var vm = {};

    vm.router = router.createChildRouter()
        .makeRelative({
            moduleId: 'viewmodels/cms',
            fromParent: true
        }).map([
            { route: ['inventory', ''], moduleId: 'inventory/overview', title: 'Inventory Management', nav: true }
        ]).buildNavigationModel();

    return vm;
});

I have placed the data-fetching logic on the activate method in overview.js

define(function(){
    var vm = {};

    vm.activate = function(){
       // fetch data here
    };

    return vm;
});

However, activate is only called the first time I navigate to that view, whereas for the views on the main router, activate is called every time.

I have tried setting cacheViews: false on the child router but that didn't change anything.

I have also realized that a binding method on my viewmodel is called every time around so:

  1. How can I enforce activate to be called every time the user navigates to the view?
  2. Is there a better hook to place my data fetching logic when I always want it to be refreshed?
  3. Alternatively, is there something inherently wrong with placing my activation logic on the binding method?
Sergi Papaseit
  • 15,999
  • 16
  • 67
  • 101
  • Have you tried returning the view model as a function and not a singleton? – Brett Oct 15 '14 at 14:44
  • Why would I need to do that for views in a child route and not for views in the main router? Doesn't make a lot of intuitive sense... – Sergi Papaseit Oct 15 '14 at 14:52
  • Are you caching views in the main router? – Brett Oct 15 '14 at 15:19
  • Nope. I tried playing with `cacheViews`, setting it to either `true` or `false` on both the main and child routers, but it made no difference – Sergi Papaseit Oct 15 '14 at 15:23
  • Have you tried setting `alwaysTriggerAttach: true` on your child router composition binding? – Brett Oct 15 '14 at 15:30
  • Yes, but that triggers `attach`, not `activate` – Sergi Papaseit Oct 15 '14 at 15:39
  • Other than returning the view model as a function constructor, idk what else to recommend. Like you said, Durandal's caching implementation has not been intuitive in my experience. – Brett Oct 15 '14 at 15:46
  • @SergiPapaseit I would say "the problem" is inside of your viewmodel. You are returning an object instead of function. I'm quoting Durandal documentation: [_"... if you return an object instance, you have created a singleton which will stay in memory for the lifetime of your application. If this is not desired, return a constructor function to retain greater control of the lifetime of your objects by allowing consumers to create/release them as needed."_]. [Read more here](http://durandaljs.com/documentation/Creating-A-Module.html) – Miloš Ostojić Oct 19 '14 at 23:03

1 Answers1

1

You should use the attached hook. This will be called everytime the view is attached to the dom.

Take a look at the Durandal Docs about Hooking Lifecycle this should give you an idea of the available hooks and what they are doing.

EDIT: Sorry maybe "should" was a bit premature, it really depends on your use-case. Both binding and attached should do the job it just depends when they are done. Binding would hook in before the DOM is applied and attached after. So it depends whether you want your user to see a white page until everything loaded, or if you want to show something and then fill up the data driven parts as the Promise of attached resolves. So really it's more a UI decision.

As for your 3rd question, loading the data isn't actually activation logic since it may happen that you re-fetch data after building the UI. Thus it's more an aspect of the data layer -> business logic, but that's a pretty philosophical question :) . Binding is totally related to pulling data right before the Knockout bindings start to kick off, so I see no problem putting that logic in binding or respectively attached if you need a smother user experience.

zewa666
  • 2,593
  • 17
  • 20
  • 1
    Can you elaborate on why the `attached` hook would be better than the `binding` hook? I am familiar with the docs but I don't feel they answer my question. – Sergi Papaseit Oct 15 '14 at 12:39
  • 1
    And actually, from what I gather from the docs, the `attached` hook comes to late in the life cycle for me to fetch the data since at that point `applyBindings` has already been called – Sergi Papaseit Oct 15 '14 at 12:41
  • I've updated my reply. sry maybe the you "should" use was a bit pre-mature – zewa666 Oct 15 '14 at 15:01