bitovi/canjs

View on GitHub
demos/can-connect/constructor-store.html

Summary

Maintainability
Test Coverage
<body>
<button id='maker'>Create Todo Editor</button>

<script src="../../node_modules/steal/steal.js" dev-bundle>
import connect from "can-connect";
import dataUrl from "can-connect/data/url/url";
import constructor from "can-connect/constructor/constructor";
import constructorStore from "can-connect/constructor/store/store";
import fixture from "can-fixture";
import mixinMapBindings from "can-event-queue/map/map";

// define a Todo type with event binding support
var Todo = function(props) { Object.assign(this, props); };
mixinMapBindings(Todo.prototype);

// connection that retrieves todos data
var todosConnection = connect([constructorStore, constructor, dataUrl], {
  url: "/todos",
  instance: function(props) {
    return new Todo(props);
  }
});

// static todo data for this example
var todo = {
  id: 5,
  name: "do the dishes"
};

// mock HTTP requests for the `todo` endpoint.
fixture({
  "GET /todos/{id}": function(){
    return todo;
  },
  "PUT /todos/{id}": function(request){
    todo.name = request.data.name;
    return {name: request.data.name};
  }
});

// generate element that edits a specified todo
var todoEditor = function(id){
  var todo;
  var element = document.createElement('div');
  element.innerHTML = "<input/><button>X</button>";

  var updateElement = function(){
    element.firstChild.value = todo.name;
  };

  // get specified todo from connection
  todosConnection.get({id: id}).then(function(retrievedTodo){
    todo = retrievedTodo; // keep returned todo so we can listen to changes on it
    updateElement(); // update input element with retrievedTodo info
    todo.on("name", updateElement); // when todo name changes update input element
    todosConnection.addInstanceReference(todo); // previous line is a new usage of todo, so increase reference count
  });

  // listen to 'X' button click
  element.lastChild.onclick = function(){
    todo.off("name", updateElement); // stop listening to todo name change
    todosConnection.deleteInstanceReference(todo); // previous line removed a usage of todo, so reduce reference count
    element.parentNode.removeChild(element); // remove this todoEditor from page
  };

  var updateData = function(newName) {
    todo.name = newName; // update name on todo instance
    todosConnection.save(todo); // save updated name to todo data source
    todo.dispatch("name"); // send name changed signal
  };

  // listen to input element onchange events
  element.firstChild.onchange = function(){
    updateData(this.value);
  };

  // listen to input element keypress events
  element.firstChild.onkeypress = function(ev){
    if(ev.keyCode === 13) { // if the enter key was pressed
      updateData(this.value);
    }
  };

  return element;
};

document.getElementById('maker').onclick = function(){
  document.body.appendChild(todoEditor(5));
};
</script>
</body>