2

maybe i missed the point of navigating in durandal, but if i want to trigger a view on a button click, how is this done?

i'm databinding a button to a click function in the viewmodel. however, when the viewmodel gets loaded, it immediately triggers the view redirect.

view:

<button data-bind="click: gotoPage('mypage')">go somewhere</button>

viewmodel:

gotoPage: function(page){

    router.navigate(page);
}
bigerock
  • 713
  • 1
  • 9
  • 29

3 Answers3

2

Can you post your whole viewmodel? maybe there is something in your activate function that is causing the redirect. Here is an example that should work:

define(['durandal/app',
    'knockout',
    'plugins/router'],
function (app, ko, router) {
    var vm = {
        CurrentEntity: ko.observable(),
        GoToPage: GoToPage
        activate: activate
    };
    return vm;

    function GoToPage(page) {
        router.navigate(page);
    };

    function activate() {
        // activation code here, make sure no redirect code exists here
    };
);

The code in the activate function will run when your model is loaded. If you have any redirect code in there that might be your problem. If you want to bypass the function all together you could also change your button to a anchor and just make the href point to your route like this:

<a href="#/MyDurandalRoute" >go somewhere</a>
Frank
  • 2,178
  • 2
  • 17
  • 24
  • My set up is nearly identical to your example - in terms of structure. My viewmodel is way too large to post, but i have an empty activate function - no code whatsoever. Also i am returning my viewmodel in the same fashion - declaring the vm variable, returning it, etc. When debugging, i watch the 'gotoPage' function getting evaluated for some reason though, even though it shouldn't unless the click event was triggered. Strange stuff. – bigerock Mar 28 '14 at 16:34
  • @bigerock when you debug the gotoPage function, can you view the call stack and see what invoked it? I would also do a text search for all files in your project and look for the word gotoPage and make sure it is not being called by some js file you are including and don't realize, have had this happen to me before. – Frank Mar 28 '14 at 20:26
1

Your javascript in the data-bind attribute, "click: gotoPage('mypage')", gets evaluated at binding time, i.e. "gotoPage('mypage')" gets executed at binding time, and the result is bound to the click event.

So you need to bind to a property, where that property points to the desired function.

In other words do this in your view:

<button data-bind="click: gotoMyPage">go somewhere</button>

and do something like this in your viewmodel:

define([
    'durandal/app',
    'knockout',
    'plugins/router'],
function (app, ko, router) {
    var vm = {
        CurrentEntity: ko.observable(),
        gotoMyPage: GoToPage
        activate: activate
    };
    return vm;

    function GoToPage() {
        router.navigate('#mypage');
    };

    function activate() {
        // activation code here, make sure no redirect code exists here
    };
);

Part B

Your GoToPage routine CAN take a parameter, e.g.

    function GoToPage(page) {
        router.navigate(page.mypage);
    };

View:

<table>
    <tbody data-bind="foreach: listOfPages">
        <tr>
            <td data-bind="text: mypage, click: gotoMyPage"></td>
        </tr>
    </tbody>
</table>

(where listOfPages contains a list of page objects, and each page object has a mypage element).

More info here: Knockout documentation on foreach

philu
  • 795
  • 1
  • 8
  • 17
0

I believe that all you are missing is the hash character in front of your route. I tried to just add a comment to Frank's answer, but don't have enough reputation as yet :(

Barry
  • 28
  • 1
  • 7
  • True, you do need to add the hash for the route to work, but his problem is that the function is being called on every load before the button click, the hash should not have any effect on that – Frank Mar 28 '14 at 22:06