The web is asynchronous. Being able to handle this in a SPA is important.
Using $page.async(Function,String/Page,[String/Page],[Observable])
makes it trivial
in your SPA.
The function $page.async
got some interesting conditions.
$.Deferred
, NOT
a $.Promise
. The reason is that the global navigation handler must be able to
#reject
the deferred. Other listeners to the deferred should be able to handle
that it is fed with the data {cancel: true}
.
null
or undefined
.
If it is defined it should have the same properties and the second argument (i.e. being
a path or page). It will decide which navigation to use if the deferred is rejected.
pending
.
If the deferred is resolved it will be set to resolved
.
If the deferred is rejected it will be set to rejected
.
See deferred.state() in the
jQuery documentation.
In this example we got two buttons (one will be resolve and one will be rejected). For brevity only one buttons model and markup is presented.
viewModel = { // wait 2 secs before returning ok wait2: function() { var d = $.Deferred(); setTimeout(function() { d.resolve(); }, 2000); return d; }, okIsLoading:ko.observable() };
and the markup
<a class="btn" data-bind="click: $page.async(wait2,'ok','notok',okIsLoading)"> Show OK page after 2 secs <!-- ko if: (okIsLoading() == 'pending') --> <img src="small-ajax-loader.gif"/> <!-- /ko --> </a>
Click on both buttons.
Show OK page after 2 secs
The hash is now changed to #!/navigation/async/ok
.
The hash is now changed to #!/navigation/async/notok
.
<div data-bind="page: { id: 'async', withOnShow: requireVM('vm/navigation/async'), title: 'Async', desc: 'handling asynchronous navigation', scrollToTop: true, sourceCache: true, sourceOnShow: 'page/navigation/async.html' }"></div>