Setup with StealJS page

Learn to set up a basic CanJS application using StealJS as the module loader.

The problem

  • Setup steal to load a basic CanJS application. A basic CanJS application has:
    • A custom element defined by Component and an instance of that custom element in the page’s HTML. That component includes a:
      • A DefineMap ViewModel and an instance of that ViewModel.
      • A stache view that is rendered with the instance of the ViewModel.
  • In addition, this application should load the can-todomvc-test module version 5.0 and pass it the custom element’s ViewModel instance. You will need to declare the version explicitly as different versions of this guide depend on different versions of this package.

What you need to know

  • To create a new project with StealJS, run:

    npm init -y
    npm install steal@2 steal-tools@2 steal-css@1 --save-dev
    
  • To host static files, install http-server and run it like:

    npm install http-server -g
    http-server -c-1
    
  • If you load StealJS plugins, add them to your package.json configuration like:

    "steal": {
      "plugins": [
        "steal-css"
      ]
    }
    
  • Define a custom element with Component:

    import {Component} from "can";
    
    Component.extend({
        tag: "todo-mvc",
        view: ...,
        ViewModel: {
           ...
        }
    });
    
  • With CanJS configured as a steal plugin, you can load stache views like:

    import view from "./path/to/template.stache";
    

    Note that can is the name of the StealJS plugin and needs to be configured as such.

  • Add the custom element to your HTML page to see it in action:

    <todo-mvc></todo-mvc>
    
  • Use the following HTML that a designer might have provided:

    <section id="todoapp">
        <header id="header">
            <h1>Todos</h1>
            <input id="new-todo" placeholder="What needs to be done?">
        </header>
        <section id="main" class="">
            <input id="toggle-all" type="checkbox">
            <label for="toggle-all">Mark all as complete</label>
            <ul id="todo-list">
                <li class="todo">
                    <div class="view">
                        <input class="toggle" type="checkbox">
                        <label>Do the dishes</label>
                        <button class="destroy"></button>
                    </div>
                    <input class="edit" type="text" value="Do the dishes">
                </li>
                <li class="todo completed">
                    <div class="view">
                        <input class="toggle" type="checkbox">
                        <label>Mow the lawn</label>
                        <button class="destroy"></button>
                    </div>
                    <input class="edit" type="text" value="Mow the lawn">
                </li>
                <li class="todo editing">
                    <div class="view">
                        <input class="toggle" type="checkbox">
                        <label>Pick up dry cleaning</label>
                        <button class="destroy"></button>
                    </div>
                    <input class="edit" type="text" value="Pick up dry cleaning">
                </li>
            </ul>
        </section>
        <footer id="footer" class="">
            <span id="todo-count">
                <strong>2</strong> items left
            </span>
            <ul id="filters">
                <li>
                    <a class="selected" href="#!">All</a>
                </li>
                <li>
                    <a href="#!active">Active</a>
                </li>
                <li>
                    <a href="#!completed">Completed</a>
                </li>
            </ul>
            <button id="clear-completed">
                Clear completed (1)
            </button>
        </footer>
    </section>
    
  • Use can-todomvc-test to load the application’s styles and run its tests:

    import test from "can-todomvc-test";
    test(appVM);
    

The solution

Click to see the solution

Create a folder:

mkdir todomvc
cd todomvc

Host it:

npm install http-server -g
http-server -c-1

Create a new project:

npm init -y

Install steal, steal-tools, and CanJS’s core modules:

npm install steal@2 steal-tools@2 steal-css@1 --save-dev
npm install can@5 steal-stache@4 --save

Add steal.plugins to package.json:

{
  "name": "todomvc",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "steal": "^2.0.2",
    "steal-css": "^1.3.2",
    "steal-tools": "^2.0.2"
  },
  "steal": {
    "plugins": [
      "steal-css","can"
    ]
  },
  "dependencies": {
    "can": "^5.2.2"
  }
}

Create the starting HTML page:

<!-- index.html -->
<todo-mvc></todo-mvc>
<script src="./node_modules/steal/steal.js" main></script>

Create the application template:

<!-- index.stache -->
<section id="todoapp">
    <header id="header">
        <h1>{{ this.appName }}</h1>
        <input id="new-todo" placeholder="What needs to be done?">
    </header>
    <section id="main" class="">
        <input id="toggle-all" type="checkbox">
        <label for="toggle-all">Mark all as complete</label>
        <ul id="todo-list">
            <li class="todo">
                <div class="view">
                    <input class="toggle" type="checkbox">
                    <label>Do the dishes</label>
                    <button class="destroy"></button>
                </div>
                <input class="edit" type="text" value="Do the dishes">
            </li>
            <li class="todo completed">
                <div class="view">
                    <input class="toggle" type="checkbox">
                    <label>Mow the lawn</label>
                    <button class="destroy"></button>
                </div>
                <input class="edit" type="text" value="Mow the lawn">
            </li>
            <li class="todo editing">
                <div class="view">
                    <input class="toggle" type="checkbox">
                    <label>Pick up dry cleaning</label>
                    <button class="destroy"></button>
                </div>
                <input class="edit" type="text" value="Pick up dry cleaning">
            </li>
        </ul>
    </section>
    <footer id="footer" class="">
        <span id="todo-count">
            <strong>2</strong> items left
        </span>
        <ul id="filters">
            <li>
                <a class="selected" href="#!">All</a>
            </li>
            <li>
                <a href="#!active">Active</a>
            </li>
            <li>
                <a href="#!completed">Completed</a>
            </li>
        </ul>
        <button id="clear-completed">
            Clear completed (1)
        </button>
    </footer>
</section>

Install the test harness:

npm install can-todomvc-test@5 --save-dev

Create the main app

// index.js
import {Component} from "can";
import view from "./index.stache";

import test from "can-todomvc-test";

Component.extend({
    tag: "todo-mvc",
    view,
    ViewModel: {
        appName: {default: "TodoMVC"}
    }
});

const appVM = window.appVM = document.querySelector("todo-mvc").viewModel;

test(appVM);