can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
763 lines (498 loc) • 19.6 kB
HTML
<!--####################################################################
THIS IS A GENERATED FILE -- ANY CHANGES MADE WILL BE OVERWRITTEN
INSTEAD CHANGE:
source: [object Object]
@function can-route.data
######################################################################## -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>CanJS - data</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" type="text/css" href="./static/bundles/bit-docs-site/static.css">
<link rel="shortcut icon" sizes="16x16 24x24 32x32 48x48 64x64" href="/docs/images/canjs_favicon.ico">
<link rel="apple-touch-icon" sizes="57x57" href="../docs/images/canjs_favicon_57x57.png">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="../docs/images/canjs_favicon_57x57.png">
<link rel="apple-touch-icon" sizes="72x72" href="../docs/images/canjs_favicon_72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="../docs/images/canjs_favicon_114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="../docs/images/canjs_favicon_128x128.png">
<link rel="apple-touch-icon" sizes="144x144" href="../docs/images/canjs_favicon_144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="../docs/images/canjs_favicon_152x152.png">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta name="apple-mobile-web-app-status-bar-style" content="white-translucent">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-2302003-11', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger"/>
<label for="nav-trigger">Menu</label>
<div id="everything">
<div id="left" class="column">
<div class="top-left">
<div class="brand">
<div class="logo">
<a href="../index.html" alt="CanJS"></a>
<div class="dropdown project-dropdown">
<a href="https://donejs.com/">DoneJS</a>
<a href="http://stealjs.com/">StealJS</a>
<a href="http://jquerypp.com/">jQuery ++</a>
<a href="https://funcunit.com/">FuncUnit</a>
<a href="http://documentjs.com/">DocumentJS</a>
</div>
</div>
<div class="version">
<div class="version-number">
3.0.0
</div>
<div class="dropdown version-dropdown">
<a href="https://v2.canjs.com">2.3.27</a>
</div>
</div>
</div>
<div class="search-bar">
<p>
</p>
</div>
</div>
<div class="bottom-left">
<div class="social-side-container">
<ul class="social-side">
<li>
<a class="header-mobile github" href="https://github.com/canjs/canjs" target="_blank"><img class="social-icon-small" src="../docs/images/github.png">Github</a>
</li>
<li>
<a class="header-mobile twitter" href="https://twitter.com/canjs" target="_blank"><img class="social-icon-small" src="../docs/images/twitter.png">Twitter</a>
</li>
</ul>
<ul class="social-side">
<li>
<a class="header-mobile" href="https://gitter.im/canjs/canjs" target="_blank">Chat</a>
</li>
<li>
<a class="header-mobile" href="http://forums.donejs.com/c/canjs" target="_blank">Forum</a>
</li>
</ul>
</div>
<ul>
<li class="
">
<a class="page"
href="guides.html"
title="Welcome to CanJS! These guides are here to help you develop and improve your relationship with CanJS. After all, picking a JavaScript framework is a commitment. We want CanJS to be the
framework you marry. This page helps you know how advance through the different stages of this
relationship:">
Guides
</a>
</li>
<li class="
parent
expanded">
<a class="page"
href="can-core.html"
title="The best, most hardened and generally useful libraries in CanJS.">
Core
</a>
<ul>
<li class="
">
<a class="module"
href="can-component.html"
title="Create a custom element that can be used to manage widgets or application logic.">
can-component
</a>
</li>
<li class="
">
<a class="module"
href="can-compute.html"
title="Create an observable value.">
can-compute
</a>
</li>
<li class="
">
<a class="module"
href="can-connect.html"
title="can-connect provides persisted data middleware. Use it to assemble powerful model layers for any JavaScript project.">
can-connect
</a>
</li>
<li class="
">
<a class="module"
href="can-define.html"
title="Exports the define method that defines observable properties and their behavior on a prototype object.">
can-define
</a>
</li>
<li class="
">
<a class="module"
href="can-define/list/list.html"
title="Create observable lists.">
can-define/list/list
</a>
</li>
<li class="
">
<a class="module"
href="can-define/map/map.html"
title="Create observable objects.">
can-define/map/map
</a>
</li>
<li class="
parent
expanded">
<a class="function"
href="can-route.html"
title="Manage browser history and client state by synchronizing the window.location.hash with a map.">
can-route
</a>
<ul>
<li>
<span>static</span>
<ul>
<li class="
">
<a class="function"
href="can-route.current.html"
title="Check if data represents the current route.">
current
</a>
</li>
<li class="current
parent
expanded">
<a class="function"
href="can-route.data.html"
title="This is the internal map underlying can-route. It can be set in order to cross-bind a top level state object (Application ViewModel) to can-route.">
data
</a>
</li>
<li class="
">
<a class="function"
href="can-route.deparam.html"
title="Extract data from a route path.">
deparam
</a>
</li>
<li class="
">
<a class="function"
href="can-route.link.html"
title="Creates a string representation of an anchor link using data and the registered routes.">
link
</a>
</li>
<li class="
">
<a class="function"
href="can-route.matched.html"
title="A compute representing the currently matched route.">
matched
</a>
</li>
<li class="
">
<a class="function"
href="can-route.param.html"
title="Get a route path from given data.">
param
</a>
</li>
<li class="
">
<a class="function"
href="can-route.ready.html"
title="Initializes can-route.">
ready
</a>
</li>
<li class="
">
<a class="function"
href="can-route.url.html"
title="Creates a URL fragment based on registered routes given a set of data.">
url
</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="
">
<a class="module"
href="can-route-pushstate.html"
title="Changes can-route to use pushstate
to change the window's pathname instead
of the hash.
var route = require("can-route-pushstate");
route("{page}", { page: "home" });
route.ready();
route.attr("page", "user");
location.pathname; // -> "/user"">
can-route-pushstate
</a>
</li>
<li class="
">
<a class="module"
href="can-set.html"
title="can-set is a utility for comparing sets that are represented by the parameters commonly passed to service requests.">
can-set
</a>
</li>
<li class="
">
<a class="module"
href="can-stache.html"
title="Live binding Mustache and Handlebars-compatible templates.">
can-stache
</a>
</li>
<li class="
">
<a class="module"
href="can-stache/helpers/route.html"
title="Adds stache helpers that use can-route.">
can-stache/helpers/route
</a>
</li>
<li class="
">
<a class="module"
href="can-stache-bindings.html"
title="Provides template event, one-way, and two-way bindings.">
can-stache-bindings
</a>
</li>
</ul>
</li>
<li class="
">
<a class="page"
href="can-ecosystem.html"
title="Useful libraries that extend or add important features to the core collection.">
Ecosystem
</a>
</li>
<li class="
">
<a class="page"
href="can-infrastructure.html"
title="Utility libraries that power the core and ecosystem collection.">
Infrastructure
</a>
</li>
<li class="
">
<a class="page"
href="can-legacy.html"
title="Former libraries that we still accept patches for, but are not under active development.">
Legacy
</a>
</li>
</ul>
</div>
</div>
<div id="right" class="column">
<div class="top-right">
<div class="top-right-top">
<ul class="top-right-bitovi">
<li class="dropdown">
<a href="http://bitovi.com" class="bitovi icon-bits">Bitovi</a>
<ul class="dropdown-menu">
<li><a href="http://bitovi.com">Bitovi.com</a></li>
<li><a href="http://bitovi.com/blog/">Blog</a></li>
<li><a href="http://bitovi.com/consulting/">Consulting</a></li>
<li><a href="http://bitovi.com/training/">Training</a></li>
<li><a href="http://bitovi.com/open-source/">Open Source</a></li>
</ul>
</li>
</ul>
<div class="brand">
<div class="logo">
<a href="../index.html" alt="CanJS"></a>
</div>
</div>
<ul class="top-right-links">
<li>
<a href="https://gitter.im/canjs/canjs">Chat</a>
</li>
<li>
<a href="http://forums.donejs.com/c/canjs">Forum</a>
</li>
<li>
<a class="github-button nav-social" href="https://github.com/canjs/canjs" data-count-href="/canjs/canjs/stargazers" data-count-api="/repos/canjs/canjs#stargazers_count">Star</a>
</li>
<li>
<a href="https://twitter.com/canjs" class="twitter-follow-button nav-social" data-show-count="true" data-show-screen-name="false">Follow @canjs</a><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</li>
</ul>
</div>
<div class="breadcrumb">
<li><a href="../index.html">CanJS</a></li> /
<li><a href="can-core.html">Core</a></li> /
<li><a href="can-route.html">can-route</a></li> /
<li><a href="can-route.data.html">data</a></li>
<li class="breadcrumb-dropdown">/ <a> On this page</a>
<ul class="on-this-page"></ul>
</li>
<div class="nav-toggle" title="Back to top"></div>
</div>
</div>
<div class="bottom-right">
<article>
<section class="title">
<div class="page-type">
<h1>data</h1>
<div>function</div>
</div>
<section class="description">
<p>This is the internal map underlying can-route. It can be set in order to cross-bind a top level state object (Application ViewModel) to can-route.</p>
</section>
</section>
<section class="on-this-page-table">
</section>
<section class="title-footer">
<ul class="title-links">
<!-- <li><a href="#">docco</a></li> -->
<li><a href="//github.com/canjs/can-route/tree/v3.0.3/route_data.md">source</a></li>
<!-- <li><a href="#">download</a></li> -->
<!-- <li><a href="#">tests</a></li> -->
</ul>
</section>
<section class="body">
<h2>Background</h2>
<p>One of the biggest challenges in a complex application is getting all the different parts of the app to talk to each other simply, cleanly, and reliably.</p>
<p>An elegant way to solve this problem is using the <a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer Pattern</a>. A single object, which can be called <a href="https://www.youtube.com/watch?v=LrzK4exG5Ss">Application ViewModel</a>, holds the high level state of the application.</p>
<h2>Use</h2>
<p>Setting <code>route.data</code> is an easy way to cross-bind your Application ViewModel object to <code>route</code>. This will serialize your Application ViewModel into the hash (or pushstate URLs).</p>
<pre><code class="language-js">var ViewModel = DefineMap.extend({
petType: "string",
storeId: "number"
});
var viewModel = new ViewModel({
petType: "string",
storeId: "number"
});
route.data = viewModel;
</code></pre>
<p><code>route.data</code> can also be set to a constructor function. A new instance will be created and bound to:</p>
<pre><code class="language-js">var ViewModel = DefineMap.extend({
page: {
type: "string",
set: function(page){
if(page === "user") {
this.verifyLoggedIn();
}
return page;
}
}
});
route.data = ViewModel;
</code></pre>
<h2>When to set it</h2>
<p>Set <code>route.data</code> at the start of the application lifecycle, before any calls to <code>route.addEventListener</code>. This will allow events to correctly bind on this new object.</p>
<h2>Demo</h2>
<p>The following shows creating an Application ViewModel that loads data at page load, has a virtual property 'locationIds' which serializes an array, and synchronizes the viewModel to can-route:</p>
<div class='demo_wrapper' data-demo-src='demos/can-route/data.html'></div>
<h2>Complete example</h2>
<p>The following example shows loading some metadata on page load, which must be loaded as part of the Application ViewModel before the components can be initialized</p>
<p>It also shows an example of a "virtual" property on the AppViewModel, locationIds, which is the serialized version of a non-serializeable can.List, locations. A setter is defined on locationIds, which will translate changes in locationIds back to the locations can.List.</p>
<pre><code class="language-js">var Location = DefineMap.extend({
selected: "boolean",
id: "any"
});
var LocationList = DefineList.extend({
"*": Location
});
var AppViewModel = DefineMap.extend({
locations: {
type: "any",
// don't serialize this property at all in the route
serialize: false
},
// virtual property that contains a comma separated list of ids
// based on locations that are selected
locationIds: {
// comma separated list of ids
serialize: function(){
var selected = thislocations.filter(
function(location){
return location.selected;
});
var ids = [];
selected.each(function(item){
ids.push(item.id);
})
return selected.join(',');
},
// toggle selected from a comma separated list of ids
set: function(val){
var arr = val;
if(typeof val === "string"){
arr = val.split(',')
}
// for each id, toggle any matched location
this.locations.forEach(function(location){
if(arr.indexOf(location.id) !== -1){
location.selected = true;
} else {
location.selected = false;
}
})
}
}
});
// initialize and set route.data first, so anything binding to can-route
// will work correctly
var viewModel = new AppViewModel();
route.data = appViewModel;
// GET /locations
var locations = new Location.List({});
// when the data is ready, set the locations property
locations.done(function(){
viewModel.locations = locations;
// call ready after the AppViewModel is fully initialized
route.ready();
});
</code></pre>
<h2>Why</h2>
<p>The Application ViewModel object, which is cross-bound to the can-route via <code>route.data</code> and represents the overall state of the application, has several obvious uses:</p>
<ul>
<li>It is passed into the various components and used to communicate their own internal state.</li>
<li>It provides deep linking and back button support. As the URL changes, Application ViewModel changes cause changes in application components.</li>
<li>It provides the ability to "save" the current state of the page, by serializing the Application ViewModel object and saving it on the backend, then restoring with that object to load this saved state.</li>
</ul>
</section>
<script type="text/javascript">
var docObject = {"src":{"path":"node_modules/can-route/route_data.md"},"description":"\nThis is the internal map underlying can-route. It can be set in order to cross-bind a top level state object (Application ViewModel) to can-route.\n","title":"data","name":"can-route.data","type":"function","parent":"can-route.static","comment":" ","pathToRoot":".."};
</script>
</article>
<footer><p>CanJS is part of <a href="http://donejs.com" target="_blank">DoneJS</a>. Created and maintained by the core <a href="https://donejs.com/About.html#section=section_Team" target="_blank">DoneJS team</a> and <a href="http://bitovi.com" target="_blank">Bitovi</a>. <strong>Currently 3.0.0.</strong></p></footer>
</div>
</div>
</div>
<script>
steal = {
instantiated: {
"bundles/bit-docs-site/static.css!$css" : null
}
};
</script>
<script type='text/javascript' data-main="bit-docs-site/static" src="./static/node_modules/steal/steal.production.js"></script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>