angular.jsのtextareaが改行されなくて困った件
もう1年以上ブログ放置してるしどうでもいいんだけど、angularJSが困ったちゃんすぎて実用化できないので書いちゃう。
やりたいことは「見たまま編集できるCMSの開発」
サーバサイドは既存のCMSそのまんまでよくて、保存とレスポンスをajaxでできるようにしただけ。
で、入力を表示をangularのリアルタイム描画にまかせようと思って組み込んだら、テキストエリアでハマった。
結局、1週間ほどトライ&エラーを繰り返し、やや強引だけど解決した。
現象
angularJSで、ビューの描画は{{モデル名}}ってやるんだけど、1行テキスト(input[text])ならそのままでOK。だけどテキストエリアは致命的で、改行が反映されない。このせいで俺の新型CMSがぽしゃってしまった。もうヤダ。
ちなみに現象のサンプルはこちら。
angularJSの一番シンプルなモデルとビューだけのサンプルはこちら。入力がリアルタイムに表示されるね、っていうだけでもてはやされてるけど、今回は使えなさそう。
完成したバージョンがこちら。
こちらは結局、angularが標準で提供しているビューを使わず、モデルの変化をチェックしてコントローラが値をgetアンドsetする、という仕組みにすることで解決した。
<!doctype html> <html ng-app> <meta charset="utf-8"> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script> <script> function myCtrl($scope, $sce){ //model $scope.form1 = { "inputvalue": "1行目\n2行目\n3行目", }, $scope.ngc = function(input,output){ //ng-changeで毎回呼び出される $scope[output] = $sce.trustAsHtml($scope.form1[input].replace(/\n/g, '<br>')); } //初回描画用 $scope.inputvalue_view = $sce.trustAsHtml($scope.form1['inputvalue'].replace(/\n/g, '<br>')); } </script> <h1>angularJS-textarea sample3(ng-controller+filter)</h1> <div ng-controller="myCtrl"> <textarea rows="5" ng-model="form1.inputvalue" ng-change="ngc('inputvalue','inputvalue_view')"></textarea> <hr> ↓ここに入力した結果が表示される <div ng-bind-html="inputvalue_view"></div> <br>{{form1.inputvalue.length}} </div> </html>
ポイントは、
・textareaタグにng-changeで関数を設定
・ビューを{{form1.inputvalue}}にせず、ゲッターにする
・そのまま表示すると自動でサニタイズされて<BR>タグがそのまま表示されてしまうのでサニタイズしない方法を探したいが、angular1.2からは「ng-bind-html-unsafe」が使えないので「ng-bind-html」にする
・それでいて値の取得は「$sce.trustAsHtml」で、HTMLとして描画する(サニタイズやエラー処理は知らんという前提)
ちなみに、上記サンプルにはないが{{form1.inputvalue.length}}と書くと文字数がカウントされる。テキストエリアは改行文字も1つとしてカウントされるようだ。