UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

535 lines (376 loc) 14.4 kB
<!DOCTYPE html> <!--#################################################################### THIS IS A GENERATED FILE -- ANY CHANGES MADE WILL BE OVERWRITTEN INSTEAD CHANGE: source: [object Object] @page guides/pmo/LoadingStates ######################################################################## --> <html lang="en"> <head> <meta charset="utf-8"> <title>CanJS - Loading States</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> &nbsp; </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="Components.html" title=""> Components </a> </li> <li class=" "> <a class="page" href="ApplicationDesign.html" title=""> Application Design </a> </li> <li class=" "> <a class="page" href="../../pmo/Setup.html" title=""> Setup </a> </li> <li class=" "> <a class="page" href="Constructors.html" title=""> Constructors </a> </li> <li class=" "> <a class="page" href="TheDefinePlugin.html" title=""> The Define Plugin </a> </li> <li class=" "> <a class="page" href="StacheTemplates.html" title=""> Stache Templates </a> </li> <li class=" "> <a class="page" href="AppStateAndRouting.html" title=""> App State and Routing </a> </li> <li class=" "> <a class="page" href="Observables.html" title=""> Observables </a> </li> <li class=" "> <a class="page" href="ViewModels.html" title=""> View Models </a> </li> <li class=" "> <a class="page" href="DataModelsAndFixtures.html" title=""> Data Models and Fixtures </a> </li> <li class="current parent expanded"> <a class="page" href="LoadingStates.html" title=""> Loading States </a> </li> <li class=" "> <a class="page" href="EventHandling.html" title=""> Event Handling </a> </li> <li class=" "> <a class="page" href="WebServiceCommunication.html" title=""> Web Service Communication </a> </li> <li class=" "> <a class="page" href="Recap.html" title=""> Recap </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="../pmo.html">Place My Order Guide</a></li> / <li><a href="LoadingStates.html">Loading States</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>Loading States</h1> <div>page</div> </div> <section class="description"> </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/canjs/tree/v3.0.0/docs/can-guides/experiment/pmo/loading-states.md">source</a></li> <!-- <li><a href="#">download</a></li> --> <!-- <li><a href="#">tests</a></li> --> </ul> </section> <section class="body"> <div class="getting-started"> <hr /> <p><strong>In this Chapter</strong></p> <ul> <li>Loading States</li> </ul> <p>Get the code for: <a href="/guides/examples/PlaceMyOrder/ch-7_canjs-getting-started.zip">chapter: loading states</a></p> <hr /> <p>Loading data from a remote server never happens immediately, so it’s a best practice to show some sort of indicator to improve the user’s experience. CanJS makes this easy with observable promises.</p> <p>Now that we have the cities and states loading from our fixtures, let’s get a list of restaurants when a city is selected. Let’s start by modifying the <code>components/restaurant_list/restaurant_list.js</code> file. Find this line:</p> <pre><code> // Restaurant code will go here </code></pre> <p>and replace it with these lines:</p> <pre><code> restaurants: { get: function(){ var city = this.attr('city'), state = this.attr('state'); return state &amp;&amp; city ? Restaurant.findAll({ 'address.state': state, 'address.city': city }) : null; } } </code></pre> <p>Here, we’re adding a new <code>restaurants</code> property that is a promise returned by <code>can.Model.findAll()</code> (if a city and state are selected). This promise has a few properties:</p> <ul> <li><code>isPending</code>: indicates that the promise hasn’t been resolved or rejected</li> <li><code>isResolved</code>: indicates that the promise has been resolved</li> <li><code>value</code>: the value of the resolved promise</li> </ul> <p>Now let’s make use of this new property and it’s attributes in our <code>components/restaurant_list/restaurant_list.stache</code> template. Find this line:</p> <pre><code> &lt;!-- Restaurants code will go here --&gt; </code></pre> <p>and replace it with these lines:</p> <pre><code> {{#if restaurants.isPending}} &lt;div class=&quot;restaurant loading&quot;&gt;&lt;/div&gt; {{/if}} {{#if restaurants.isResolved}} {{#each restaurants.value}} &lt;div class=&quot;restaurant&quot;&gt; &lt;img src=&quot;{{images.thumbnail}}&quot; width=&quot;100&quot; height=&quot;100&quot;&gt; &lt;h3&gt;{{name}}&lt;/h3&gt; {{#address}} &lt;div class=&quot;address&quot;&gt; {{street}}&lt;br /&gt;{{city}}, {{state}} {{zip}} &lt;/div&gt; {{/address}} &lt;div class=&quot;hours-price&quot;&gt; $$$&lt;br /&gt; Hours: M-F 10am-11pm &lt;span class=&quot;open-now&quot;&gt;Open Now&lt;/span&gt; &lt;/div&gt; &lt;a class=&quot;btn&quot; href=&quot;{{ routeUrl(page='restaurants' slug=slug) }}&quot;&gt;Place My Order&lt;/a&gt; &lt;br /&gt; &lt;/div&gt; {{/each}} {{/if}} </code></pre> <p>You’ll notice the <code>{{#if restaurants.isPending}}</code> and <code>{{#if restaurants.isResolved}}</code> lines; the first is for showing a loading indicator while the restaurants are being loaded, and the second is for showing the list of restaurants once they’ve been fetched from the server (or in our case, from the fixtures). After they have, <code>{{#each restaurants.value}}</code> iterates over the list of restaurants to show them on the page.</p> <p>Speaking of fixtures, let’s modify our <code>models/fixtures.js</code> file. Add the following lines:</p> <pre><code>can.fixture('GET /api/restaurants', 'models/restaurants.json'); can.fixture('GET /api/restaurants/{_id}', 'models/spago.json'); </code></pre> <p>The first line will let us make a <code>GET</code> request to <code>/api/restaurants</code> to fetch the list of restaurants. The second line will return data for a specific restaurant. Normally, this would be dynamic, depending on which restaurant we want info for. For simplicity, however, we’re responding with the same fixture data regardless of which restaurant is requested.</p> <p>Go ahead and refresh the Restaurants page in your browser. Now, we can select a state, a city, and then immediately see a list of restaurants!</p> <p><img src="../can/guides/images/application-design/RestaurantList.png" alt="Restaurant list" /></p> <hr /> <p><span class="pull-left"><a href="DataModelsAndFixtures.html">&lsaquo; Data Models and Fixtures</a></span> <span class="pull-right"><a href="EventHandling.html">Event Handling &rsaquo;</a></span></p> </div> </section> <script type="text/javascript"> var docObject = {"src":{"path":"docs/can-guides/experiment/pmo/loading-states.md"},"description":"\n","name":"guides/pmo/LoadingStates","title":"Loading States","type":"page","parent":"guides/pmo","order":10,"disabletableofcontents":true,"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>