4
votes

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?
1
Have you tried returning the view model as a function and not a singleton?Brett
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
Are you caching views in the main router?Brett
Nope. I tried playing with cacheViews, setting it to either true or false on both the main and child routers, but it made no differenceSergi Papaseit
Have you tried setting alwaysTriggerAttach: true on your child router composition binding?Brett

1 Answers

1
votes

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.