Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="CanJS 4 - Counter">
  
  <script src="https://unpkg.com/can@4/dist/global/can.all.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body noscroll>
  <p>Click the tasks and home link. Notice how the 
     page is updated.</p>
  <p>Check `isSaving`. Notice the page does not update.  Uncheck `isSaving`, the page will then match the hash.</p>
  <my-app></my-app>
</body>
</html>
 
can.route.register("{page}",{page: "index"})
can.Component.extend({
  tag: "my-app",
  view: `
    <h1>My App</h1>
    <p>isSaving: <input type="checkbox" checked:bind="isSaving"/></p>
    <p>Real route: <b>{{routeData.page}}</b> | Shield route: <b>{{shieldData.page}}</b></p>
    {{# eq(shieldData.page, "index") }}
      <h2>Home</h2>
      <a href="{{routeUrl(page='tasks')}}">tasks</a>
    {{ else }}
      <h2>Tasks</h2>
      <a href="{{routeUrl(page='index')}}">home</a>
    {{/ eq }}
    
    <dialog {{#if(showConfirm)}}open{{/if}}>
      <p>Do you want to leave this page?</p>
      <button on:click="cancelDialog()">No</button>&nbsp;
      <button on:click="confirmDialog()">Yes</button>
    </dialog>
    
  `,
  ViewModel: {
    init(){
      can.route.data = this.routeData;
      can.route.start();
    },
    // the actual stateful values from the url
    routeData: {default() { return new can.DefineMap() } },
    // if we have some state where we don't want it to look like the url has changed right away
    isSaving: "boolean",
    
    showConfirm: "boolean",
    // A getter used mostly so we can know when any data in the URL changed
    get routeDataClone(){
      return this.routeData.get()
    },
    // this will have the old `routeData` if isSaving is true:
    shieldData: {
      value({resolve, listenTo}){
        
        // A place to store the last route data
        var savedData;
        var oldData;
        // When the route data changes
        listenTo("routeDataClone", function(ev, newData){
          // if we are saving, save the new data
          if(this.isSaving){
            console.log('store:' +  window.location.hash);
            savedData = newData;
            this.showConfirm = true;
          } else {
            console.log('go:' +  window.location.hash);
            resolve(newData); // if we aren't saving, update
          }
          oldData = newData;
        });
        
        resolve(this.routeDataClone);
    
        listenTo("isSaving", function(ev,newValue){
        // when saving state changes to false
        // check if there was some route changes and apply them
          if(!newValue && savedData !== undefined) {
            resolve(savedData);
            console.log('resolve:' +  window.location.hash);
            savedData = undefined;
          }
        })
      }
    },
    
    cancelDialog() {
      console.log('cancel:' + window.location.hash);
      this.showConfirm = false;
    },
    
    confirmDialog() {
      console.log('confirm:' + window.location.hash);
      this.isSaving = false;
      this.showConfirm = false;
    },
    
  }
});
Output

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

Dismiss x
public
Bin info
jeroencornelissenpro
0viewers