2

I have a pretty simple thing I want to accomplish but I cannot figure out how or if it is even possible. I am using the Hot Towel template to start with. In the shell viewmodel I have a user observable. I would like to be able to reference that user observable from other pages on my site. For example from the home page. I tried a couple of things but it doenst appear as though I can access the shell from the composed view. I have a working solution at the moment that uses event pub/sub calls from the shell to pass the user data to anyone listening whenever the data changes (home view in this example). This works it just seems a little clunky and not really the ideal way to handle this. This user observable will need to be used all throughout the site to determine when certain features should be available and to show a particular users projects.

Is there a way to data bind to a knockout observable contained in the shell viewmodel from the home view?

OriginalMoose
  • 177
  • 16

3 Answers3

4

You might consider having a global.js that returns a singleton, which you include in view models as needed.

define(function () {

    return {
        sharedObservable: ko.observable(),
        sharedObservableArray: ko.observableArray(),
        ...
    };
});

Using global in a viewmodel.

define([..., global], function (..., global) {
    ...
    global.sharedObservable('updated');

    // As an alternative use a local var for easier access
    // var localVar = global.sharedObservable;
    // localVar('updated') 
    ...

});
RainerAtSpirit
  • 3,723
  • 1
  • 17
  • 18
  • I like this solution much better than the pub/sub I was doing before. I gave it a quick try and everything seems to be working. Thanks for your help. – OriginalMoose May 23 '13 at 19:29
  • 1
    To tag onto Rainer's answer, I have just learned in the last few days how to take this a step further and use data-bind="text: global.sharedObservable" in the view to reference an observable from the global.js as well. Just expose global to your view from your view model and everything stays happy. I found this helpful to reduce replicating data (such as using localVar(global.sharedObservable()); and then displaying localVar on the view) – PW Kad May 23 '13 at 21:10
0

The easiest way is to import the shell module into your viewmodel with requirejs and then expose the shell viewmodel as a variable on the module's viewmodel.

Somehting like this:

// Some viewmodel
define(['shell'], function(shell){
     var vm = {
         shell: shell,
         ...
     };
     return vm;
});

Then in your view, you can bind using $root.shell

<span data-bind="text: $root.shell.shellObservable"></span>
Jacques Snyman
  • 4,115
  • 1
  • 29
  • 49
0

Non of previous answers worked for me. Thus, I tried another variant of access to shell and it made the job done.

I've got this in my shell.js:

    define(['plugins/router', 'durandal/app'], function (router, app) {
      return {
        // I need an access to this array in my view
        breadcrumbs: ko.observableArray([]), 
        ...
        };
   });

And this in my view:

define(function () {
    var ctor = function () {
        this.pageTitle = 'Preview';
        this.activate = function () {
            require('viewmodels/shell').breadcrumbs([...]);
        };
    };
    return ctor;
});

So, require('viewmodels/shell') actually returns reference to a shell object.