タスクの新規追加フォーム

2015/07/01

前回は、データストアという Cape.JS の重要な概念について解説しました。

今回は、タスクを新規追加するフォームを表示する方法について解説します。


本題に入る前に、準備作業としてソースコードの整理整頓(リファクタリング)を行いましょう。

todo_list.es6 のソースコードは現在こうなっています。

class TodoList extends Cape.Component {
  init() {
    this.ds = new TaskStore();
    this.ds.attach(this);
    this.ds.refresh();
  }

  render(m) {
    m.ul(m => {
      this.ds.tasks.forEach(task => {
        m.li(m => {
          m.class({ completed: task.done });
          m.label(m => {
            m.onclick(e => this.ds.toggleTask(task));
            m.input({ type: 'checkbox', checked: task.done }).sp();
            m.span(task.title);
          });
        });
      });
    });
  }
}

今後 render() メソッドの中身が増えていくことが予想されるので、次のように一部を別メソッドとして分離します。

class TodoList extends Cape.Component {
  init() { ... }

  render(m) {
    m.ul(m => {
      this.ds.tasks.forEach(task => {
        m.li(m => this.renderTask(m, task));
      });
    });
  }

  renderTask(m, task) {
    m.class({ completed: task.done });
    m.label(m => {
      m.onclick(e => this.ds.toggleTask(task));
      m.input({ type: 'checkbox', checked: task.done }).sp();
      m.span(task.title);
    });
  }
}

では、タスクを新規追加するフォームをタスク一覧の下に表示しましょう。

class TodoList extends Cape.Component {
  init() { ... }

  render(m) {
    m.ul(m => {
      this.ds.tasks.forEach(task => {
        m.li(m => this.renderTask(m, task));
      });
    });
    this.renderCreateForm(m);
  }

  renderTask(m, task) { ... }

  renderCreateForm(m) {
    m.formFor('new_task', m => {
      m.textField('title').sp();
      m.btn('Add task');
    });
  }
}

この連載で初登場のメソッドが3つあります。formFor()textField()btn() です。

formFor()<form> 要素を生成します。第1引数にはフォームの名前を文字列で指定します。この名前は <form> 要素の name 属性の値として使われます。コンポーネントの内部で一意(unique)である必要があります。

Cape.JS のマークアップビルダーはすべての有効な HTML 要素の名前に対応するメソッドを持っていますので、form() というメソッドで <form> 要素を生成することもできます。しかし、次回以降で説明する val()paramsFor() などの便利なメソッドを利用するためには formFor() を使う必要があります。

textField() はテキスト入力欄(<input type="text"> 要素)を生成します。引数にはフィールド名を文字列で指定してください。

btn() は汎用ボタン(<button type="button"> 要素)を生成します。引数にはラベル文字列を指定します。

m.button('Add task', { type: 'button' }) のように書いても構いません。しかし、btn() メソッドを使った方が簡単です。

では、動作確認をしましょう。サーバーを起動してブラウザでトップページにアクセスすると、次のような画面になります。

画面キャプチャ

念のため「Add task」ボタンをクリックして何の反応も起きないことを確認してください。


さて、前々回の記事で触れましたが、ES6 ではバッククオートによる式の埋め込みができることを覚えているでしょうか。

このテクニックを使ってみましょう。renderCreateForm() のコードを次のように書き換えてください。

  renderCreateForm(m) {
    m.formFor('new_task', m => {
      m.textField('title').sp();
      m.btn(`Add task #${ this.ds.tasks.length + 1 }`);
    });
  }

バッククオートで囲まれた文字列の中に ${ ... } という形式の文字列を書くと、その部分に式の値が文字列に変換されて埋め込まれます。ここでは this.ds.tasks.length + 1 という式を埋め込んでいます。この式は、現在のタスクの個数に 1 を加えたものになります。ブラウザをリロードすると、次のような画面に変化します。

画面キャプチャ


今回はここまで。

次回は、このフォームを使って新規タスクを追加する機能を実装します。