Angular2 でWisyエディタを使ってみる


# 前置き

とりあえず、下記の２エディタに関してAngularJS2との併用が可能であることを確認できた。
https://github.com/xing/wysihtml5
https://www.tinymce.com/


1. １画面に複数のエディタが必要であり、tinymceだとちょっと重たくなってしまった
2. wysihtml5はデザイン修正がやりやすく、ソースも理解しやすかった

といった理由から、今回はwisyhtml5を利用してみた。
wisyhtml5を利用して困ったこともあったが、なんとか直して使っている状態である。
https://github.com/itoufo/wysihtml5

ちなみに、導入に関してはTinymceの方が簡単だったので、こちらを参考に実装できると思う。

# Demo
デモである。後のクオリティはデザイン次第
https://plnkr.co/edit/7TODGCdDGPLAo3u6oPVR

# 定義ファイルを用意する

TypeScriptを利用して開発している場合、外部ライブラリのオブジェクト構造を記載した定義ファイル(.d.ts)が必要になる。なくても動くけど。

そんなわけで、少なくとも私に必要な限りの定義を記載したファイルを作ってみた。
https://github.com/itoufo/wysihtml5.d.ts/blob/master/wysihtml.d.ts

とりあえずこいつをAngularプロジェクト配下においておく

# 設定ファイルを用意する

エディタの動作を規定する設定ファイルを用意してhtmlから読み込ませる。
基本的に下記を使えば良いと思っている。
https://github.com/Voog/wysihtml/blob/master/parser_rules/advanced.js

Html ファイルからは上記のファイルと wysihtml本体を入れてやればいい。

```index.html
<script src="https://rawgit.com/itoufo/wysihtml5/master/dist/wysihtml5-0.4.0pre.min.js"></script>
<script src="parser_rules.js"></script>

```

# HTMLを作成する
デモでは app.ts でtemplateに設定している部分である。
WisyEditorの場合ツールバー部分が膨大で、ボタンのコマンドとデザインを一つ一つ書いている。
行は多くなるけど、カスタマイズは簡単でデザインもCSSでできる（後述）。

```html:wisy5.html
    <div>
      <h2>Hello {{name}}</h2>
        
      <!-- ツールバー こっから -->
      <div class="wysihtml5-toolbar" id="{{toolbarId}}" style="display: none;">

        <a class="wysiwyg-command wysiwyg-bold"
           data-wysihtml5-command="bold">Bold</a>
        <a class="wysiwyg-command wysiwyg-italic"
           data-wysihtml5-command="italic">Italic</a>

        <!-- Some wysihtml5 commands require extra parameters -->
        <a class="wysiwyg-command wysiwyg-color wysiwyg-color-red"
           data-wysihtml5-command="foreColor"
           data-wysihtml5-command-value="red">R</a>
        <a class="wysiwyg-command wysiwyg-color wysiwyg-color-green"
           data-wysihtml5-command="foreColor"
           data-wysihtml5-command-value="green">G</a>
        <a class="wysiwyg-command wysiwyg-color wysiwyg-color-blue"
           data-wysihtml5-command="foreColor"
           data-wysihtml5-command-value="blue">B</a>

        <a class="wysiwyg-command wysiwyg-list wysiwyg-list-ordered"
           data-wysihtml5-command="insertOrderedList">ol
        </a>

        <a class="wysiwyg-command wysiwyg-list wysiwyg-list-unordered"
           data-wysihtml5-command="insertUnorderedList">ul
        </a>

        <!-- Some wysihtml5 commands like 'createLink' require extra paramaters specified by the user (eg. href) -->
        <a class="wysiwyg-command"
           data-wysihtml5-command="createLink"><i class="fa fa-link"></i></a>
        <div data-wysihtml5-dialog="createLink" style="display: none;">
          Link:
          <input data-wysihtml5-dialog-field="href" value="http://" class="text">
          <a data-wysihtml5-dialog-action="save">OK</a> <a data-wysihtml5-dialog-action="cancel">Cancel</a>
        </div>

        <!-- User can define the image's src: -->
        <a class="wysiwyg-command"
           data-wysihtml5-command="insertImage"><i class="fa fa-file-image-o"></i></a>
        <div data-wysihtml5-dialog="insertImage" style="display: none;">
          Image:
          <input data-wysihtml5-dialog-field="src" value="http://">
          <a data-wysihtml5-dialog-action="save">OK</a>
          <a data-wysihtml5-dialog-action="cancel">Cancel</a>
        </div>
        <!-- Pre-defined src -->
      </div>
      <!-- ツールバー ここまで -->
      
      <textarea id="{{editorId}}"></textarea>
      
    </div>
```

## 描写後(AfterViewInit)でエディタを作成する
後は簡単で、テンプレートに設定した editorIdとtoolbarIdを元に初期化するだけ使えるようになる。

ここでOnInitやOnChangesを利用して初期化すると、描写されておらずエラーが発生するので注意。

ただしこのコンポーネントから別のコンポーネントに遷移したりすることを想定すると色々問題が発生する。その辺りのことはまた後日書いてみよーと思ってはいる。

```ts:app.ts
//our root app component
import {Component, AfterViewInit} from 'angular2/core'

@Component({
  selector: 'my-app',
  providers: [],
  template: `wysihtml5.html`,
  directives: []
})
export class App implements AfterViewInit{
  editorId = "wisysample"
  toolbarId = "wisytoolbar"
  private _editor: WysihtmlEditor;
  
  constructor() {
    this.name = 'Angular2'
  }
  
  ngAfterViewInit() {
    this._editor = new wysihtml5.Editor( this.editorId, { // id of textarea element
      toolbar: this.toolbarId, // id of toolbar element
      parserRules: wysihtml5ParserRules, // defined in parser rules set
      stylesheets: ["wysihtml5.css"]
    });  
  }
}
```