Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="CanJS Models">
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<script id="app-template" type="text/stache">
{{#eq page 'home'}}
  <home-page/>
{{else}}
  <restaurants-page/>
{{/eq}}
</script>
  
<script id="home-template" type="text/stache">
<h1>Home Page</h1>
<a href="{{routeUrl page='restaurants'}}">
  Find a restaurant
</a>
</script>
  
<script type="text/stache" id="select-loader-template">
{{^if promise.isResolved}}
  <select disabled>
    {{#if promise}}
      <option>{{loadingText}}</option>
    {{/if}}
  </select>
{{else}}
    <select {($value)}="value">
      {{^value}}
        <option value="">{{chooseText}}</option>
      {{/value}}
      <content/>
    </select>
{{/if}}
</script>
  
<script type="text/stache" id="restaurants-page-template">
<h2>Find a restaurant
<a href="{{routeUrl page='home'}}">
  home
</a>
</h2>
<form>
  <label>State</label>
  <select-loader 
    {promise}="states" {(value)}="state"
    loading-text="Loading states"
    choose-text="Choose state">
    {{#each states.value}}
        <option value="{{short}}">{{name}}</option>
      {{/each}}
  </select-loader>
  
  <label>City</label>
  <select-loader {promise}="cities" {(value)}="city">
    {{#each cities.value}}
      <option>{{name}}</option>
    {{/each}}
  </select-loader>
  
</form>
{{#if restaurants.isPending}}
  <div class="restaurant loading">Loading...</div>
{{/if}}
{{#each restaurants.value}}
  <div class="restaurant">
    <img src="{{images.thumbnail}}" width="100" height="100">
    <h3>{{name}}</h3>
      
    <div class="address">
        {{#address}}{{city}}, {{state}}{{/address}}
    </div>
    
  </div>
{{/each}}
</script>
  
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.js"></script>
<script src="//canjs.com/release/latest/can.jquery.js"></script>
<script src="//canjs.com/release/latest/can.construct.super.js"></script>
<script src="//canjs.com/release/latest/can.map.define.js"></script>
<script src="//canjs.com/release/latest/can.stache.js"></script>
<script src="//canjs.com/release/latest/can.fixture.js"></script>
</body>
</html>
 
.restaurant {
  margin: 20px 0px;
  clear: left;
  img {
    float: left;
    margin-right: 5px;
  }
  h3 {
    padding: 5px;
    margin: 0px;
    font-size: 30px;
  }
  .address {
    padding: 5px;
  }
}
restaurants-page {
  a {font-size: 12pt; font-weight: normal;}
}
 
defineModels();
defineComponents();
// Define a Map type that will be connected
// to the browser's URL.
var AppViewModel = can.Map.extend({
  define: {}
});
// Create an instance of that map
var appViewModel = new AppViewModel();
// Connect the map to the browser's URL
can.route.map(appViewModel);
// Define pretty routing rules
can.route(":page",{page: "home"});
// Start the two-way binding between the URL 
// and the `appViewModel`.
can.route.ready();
// Render the main template with the appViewModel.
$("body").append(
  can.view("app-template",appViewModel) 
);
function defineComponents(){
  can.Component.extend({
    tag: "home-page",
    template: can.view('home-template')
  });
  
  can.Component.extend({
    tag: "select-loader",
    template: can.view("select-loader-template"),
    viewModel: {
      loadingText: "Loading...",
      chooseText: "Choose"
    }
  });
  
  var RestaurantListVM = can.Map.extend({
    define: {
      states: {
        value: function() {
          return State.findAll({});
        }
      },
      state: {
        value: '',
        type: 'string',
        set: function() {
          // Remove the city when the state changes
          this.attr('city', null);
        }
      },
      city: {
        type: 'string'
      },
      cities: {
        get: function() {
          
          var state = this.attr('state');
          if(!state) {
            return null;
          }
  
          return City.findAll({ state: state });
        }
      },
      restaurants: {
        get: function() {
          var state = this.attr('state'),
              city = this.attr('city');
          if(state && city) {
            return Restaurant.findAll({
              'address.state': state,
              'address.city': city
            });
          }
          
          return null;
        }
      }
    }
  });
  
  can.Component.extend({
    tag: "restaurants-page",
    template: can.view('restaurants-page-template'),
    viewModel: RestaurantListVM
  });
}
function defineModels(){
  var stateStore = can.fixture.store([
    { name: 'California', short: 'CA' },
    { name: 'New York', short: 'NY'}
  ],{});
    
  
  var cityStore = can.fixture.store([
    { state: 'CA', name: 'San Francisco' },
    { state: 'CA', name: 'Los Angeles' },
    { state: 'NY', name: 'New York' },
    { state: 'NY', name: 'Albany' }
  ],{});
  can.fixture({
    'GET /api/states': stateStore.findAll,
    'GET /api/cities': cityStore.findAll,
    'GET /api/restaurants': function(req){
      return [{
        _id: 1,
        name: 'Cheese City', slug:'cheese-city',
        images: {
          thumbnail: "http://www.place-my-order.com/node_modules/place-my-order-assets/images/1-thumbnail.jpg"
        },
        address: {
          city: req.data['address.city'],
          state: req.data['address.state']
        }
      },
      {
        _id: 2,
        name: 'Crab Barn', slug:'crab-barn',
        images: {
          thumbnail: "http://www.place-my-order.com/node_modules/place-my-order-assets/images/2-thumbnail.jpg"
        },
        address: {
          city: req.data['address.city'],
          state: req.data['address.state']
        }
      }];
    }
  });
  can.fixture.delay = 2000;
  
  State = can.Model.extend({
    resource: "/api/states",
    id: "short"
  },{});
  
  City = can.Model.extend({
    resource: "/api/cities",
    id: "name"
  },{});
  
  Restaurant = can.Model.extend({
    resource: "/api/restaurants"
  },{});
}
Output 300px

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
justinbmeyerpro
0viewers