今回はメモを削除できるようにします。

削除だけだと、あまりにも内容が薄いので、少し細かい部分も実装します。

削除ボタンの設置と削除処理

削除ボタンは一覧画面に設置することにしました。

FontAwesomeアイコンのxマークで削除ボタンを表現しています。

/**
 * メモ一覧リストクラス。
 *
 * @class Memo.view.list.List
 * @extend Ext.List
 */
Ext.define(Memo.view.list.List, {
    extend: Ext.List,
    xtype: list_list,

    cls: list-list,

    itemTpl: [
        <div class="content">,
            <h2 class="title">{title}</h2>,
            <p class="body">{body}</p>,
        </div>,
        <div class="action">,
            <i class="btn-remove fa fa-remove"></i>,
        </div>
    ],

    store: Memo,

    listeners: {
        itemtap: onItemTap
    }
});

/**
 * メモ一覧ビューコントローラクラス。
 *
 * @class Memo.view.list.ViewController
 * @extend Ext.app.ViewController
 */
Ext.define(Memo.view.list.ViewController, {
    extend: Ext.app.ViewController,
    alias: controller.list,

    /**
     * showscreenイベント時の処理。
     */
    onShowScreen: function () {
        Ext.getStore(Memo).load();
    },

    /**
     * 新規作成ボタンタップ時の処理。
     */
    onTapCreateButton: function () {
        this.redirectTo(regist, true);
    },

    /**
     * リストitemtapイベント時の処理。
     *
     * @param {Memo.view.list.List} list リスト
     * @param {Number} index インデックス番号
     * @param {Ext.dom.Element} target タップ要素
     * @param {Memo.model.Memo} record メモモデル
     * @param {Ext.event.Event} e イベントオブジェクト
     */
    onItemTap: function (list, index, target, record, e) {
        var me = this,
            el = Ext.fly(e.target),
            store = Ext.getStore(Memo);

        if (el.hasCls(btn-remove)) {
            Ext.Msg.confirm(確認, メモを削除します。よろしいですか?, function (btn) {
                if (btn === yes) {
                    store.remove(record);
                    store.sync();
                }
            });

            // 行選択を中断するためにfalseを返す
            return false;
        } else {
            me.redirectTo(regist/ + record.getId(), true);
        }
    }
});

ボタンの位置はスタイルシートで調整します。↓のような内容で、sass/src/view/list/List.scssを作成しました(ベンダープレフィックスは手抜きです)。

@charset "UTF-8";

.list-list {
  .x-listitem-body {
    .x-innerhtml {
      display: flex;

      .content {
        flex: 1;
      }

      .action {
        .btn-remove {
          font-size: 1.5em;
        }
      }
    }
  }
}

onItemTapの処理に、削除ボタンをタップされたかどうかの判定と削除処理を追加しています。

判定方法は、classicの時と同じくタップした要素のセレクタ名で行っています。

データの削除は特筆するほどでもないですね(remove => sync)。

最後にonItemTapでretrun falseを追加しています。falseを返すと、itemtapイベントより先の処理を中断することができます。具体的には、行の選択に関する処理まで進まなくなり、タップしたときの背景色が付かなくなります。

改行対応とHTMLエスケープ

今回のネタ不足を補うために、本文に改行含みの文章を保存したときに一覧画面で表示するコードを紹介します。

f:id:sham-memo:20170125215940p:plain

↑のような入力をした場合、一覧画面では次のようになります。

f:id:sham-memo:20170125220125p:plain

もちろんこれでは駄目ですね。そこで↓のようにします。

/**
 * メモ一覧リストクラス。
 *
 * @class Memo.view.list.List
 * @extend Ext.List
 */
Ext.define(Memo.view.list.List, {
    extend: Ext.List,
    xtype: list_list,

    cls: list-list,

    itemTpl: [
        <div class="content">,
            <h2 class="title">{[this.br(values.title)]}</h2>,
            <p class="body">{[this.br(values.body)]}</p>,
        </div>,
        <div class="action">,
            <i class="btn-remove fa fa-remove"></i>,
        </div>,
        {
            br: function (text) {
                text = Ext.String.htmlEncode(text);
                return text.replace(/
?
/g, <br/>)
            }
        }
    ],

    store: Memo,

    listeners: {
        itemtap: onItemTap
    }
});

itemTplは内部的にはExt.XTemplateになるため、その機能を使うことができます。

その機能の一つとして、テンプレート内で使える関数を定義することができます。

その方法は、配列の最後にオブジェクトリテラルを追加し、そこに関数を定義します。すると、{[this.xxx()]}のように記述することで、その関数を呼び出すことが可能です。{[…]}で記述する場合、valuesという予約変数から全ての値を参照できます。

エスケープ処理は、Ext.String.htmlEncodeで用意されているので、それを使います。改行文字を
に置き換えるのは一般的な方法で行っています。

エスケープ + 改行処理を、共通関数として用意しておくと、他の画面でも使えて便利になりますよ。

f:id:sham-memo:20170125221434p:plain

↑のように、きれいに表示されるようになりました。

 

 

 

メモ登録機能としては最低限のことができるようになったので、チュートリアルは今回で終わりにしようと思います。次回からはメモ登録とは関係ない機能を取り上げていこうと思います。