管理画面のようなものを作るとき、しばしば利用されるwysiwygエディタ(htmlタグを埋め込めるエディタ)。
railsで利用しようと思ったとき手軽に入れられるのはgem対応しているckeditor等ですが、さすが見た目がダサすぎるしフロントエンドのテクノロジーもだいぶ進化を遂げているということでreactで動くfacebook製エディタdraft-jsを利用してみました。
draft-js
##動作環境
rails 5系 or 4系
####gem
react-rails
browserify-rails
####npm
react@15.4.1
react-dom@15.4.1
draft-js@0.9.1
browserify@13.1.1
browserify-incremental@3.1.1
##どこまでフロントをレールに乗せるか
近年はrailsのレールからフロントエンドの技術をあえて外していく流れがあるようで、sprocketがショボいとかパッケージ管理はnpmよりbowerがいいとか色々な話があったのですが、とにかく今回は簡単にdraft-jsを導入しようということでnpmでnode系パッケージを管理するにとどまっています。react-railsとbrowserify-railsを利用しているためgemとnpmに跨ったライブラリ管理になっているのは違和感ではあるんですけど。
##手順
手順は非常に単純です。
1.パッケージのインストール
2.assets系の設定
3.draft-js導入
###1.パッケージのインストール
それぞれgemとnpmで入れるものがあるので進めていきましょう。
少し複雑なんですがreact_componentを利用するためにreact-railsをgemでインストールし、react本体はnpmでインストールします。
browserify-railsについても同様でbrowserify本体はnpmからインストールします。
gem 'react-rails'
gem 'browserify-rails'
bundle install(インストール場所はお好きにどうぞ)とreact-railsの初期化
$ bundle install --path=vendor/bundle
$ rails g react:install
npmはコマンドラインからrailsでインストールしましょう。
$ npm install browserify browserify-incremental react react-dom reactify --save
###2.assets系の設定
draft-jsを定義するReactComponentを作成
$ rails g react:component Draft
application.rbとapplication.jsにそれぞれ設定を書き込んでいきます。
application.rbにはnpmの読み込みとbrowserifyのoptionを設定します。
class Application < Rails::Application
#略
config.assets.paths << Rails.root.join('node_modules')
config.browserify_rails.commandline_options = "--t babelify"
#略
end
application.jsにはassetsの読み込み設定を書き込みます。
おそらくrequire react
やrequire react-dom
といった記述があるかと思いますが、今回はnpmからreactを利用するので削除します。components.jsの読み込みは規約となっておりreact_componentの読み込みはこちらで行います。またcomponent自体はcomponentsディレクトリに保存していきます。
//= require jquery
//= require jquery_ujs
//= require components
//
//= require_self
//= require react_ujs
window.React = require('react');
window.ReactDOM = require('react-dom');
window.Draft = require('./components/draft.js.jsx');
###3.draft-js導入
2で定義しているdraft.js.jsxにdraft-jsを実装していくわけですが、今回はこの辺を参考にしてコピペしました。コピペなのでコードは省略します、ご了承ください。
const {Editor, EditorState, RichUtils} = Draft;
class RichEditorExample extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.focus = () => this.refs.editor.focus();
this.onChange = (editorState) => this.setState({editorState});
this.handleKeyCommand = (command) => this._handleKeyCommand(command);
this.onTab = (e) => this._onTab(e);
this.toggleBlockType = (type) => this._toggleBlockType(type);
this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
}
/*------略-------*/
このままだと見た目がダサいのでcssのほうも公式から頂戴しましょう、assets/stylesheets/application.scssと並列にcssを配置します。
最後に作成したcomponentをviewで読み込みます。今回はroot設定とかは省略しますがご了承ください。
<%= react_component('Draft') %>
##所感
フロントの技術は正直いろいろ有りすぎて戸惑いましたがサーバー側の人間も今後向き合っていかないといけないものだなと感じました。Reactとか完全に裏側の人がやるための設計ですしね。
それにしてもReactとwysiwygエディタは相性が良さそうだしいくらでも便利なのがあると思ったんですが、なかなかコレと即決できるものがなく、フロントの技術は今まさに発展しているものなのだとしみじみ感じました。
draft-js用のpluginだと下記ページ充実しているのでよければご覧ください。
https://www.draft-js-plugins.com/