[AngularJS]$scopeを超えてデータ(model)をやりとりする[夏休み企画5]

AngularJSでは、コントローラーのネストが可能です。

例えば、よくあるサンプルで

このようにすれば、diaryCtrl内で$scope.articlesを宣言し、
データを配列で格納すれば、li要素が配列の要素数だけ繰り返されます。

ざっくりですが、li要素内のtable要素は、最初に記述されている
{{article.title}}をクリックすると、詳細が確認できるようになっている、とします。

※イメージが難しければ前回のTodoMVCの解説の記事にあった、実際に
動作させているリンクを確認していただければと思います。ダブルクリックすると
todoの内容を編集できるtextboxが表示されますが、あれと同じ要領だと思っていただれば
と思います。

通常はこれで問題ないのですが、例えば

  • 編集や確認をしたい要素が大量にある
  • modelのstyle(CSS)を編集するためのformを用意したい
  • ng-repeatしている要素が大量にある

などの理由で、どうにかtableをarticleCtrlの外に出したいときや、
詳細表示用や編集のためのviewをひとつだけにして、
内容だけを切り替えて表示したいとき、なんかがあります。。

※僕の場合は、ng-repeatさせているdiv要素のopacityとz-indexを変更させたかったのですが
、controller内のformやinput要素で編集を行うと、z-indexを変更した瞬間にformごと
全体を囲っているdiv.wrapper後ろにいってしまう、という問題がありました。

なので、こんな感じにしたいんです。

こういうときに、クリックされたarticleはarticleCtrl内のscopeに
含まれているので、blogCtrlからアクセスができません。

要するに、クリックされたarticleCtrl内の$scope.articleを、
blogCtrlに渡せれば万事解決です。

結論からいうと、簡単にできます。これだけ

angular.element()では、jQueryのlite版(jqLite)のラッパーです。
つまり、jQueryと同様のセレクタを指定できます。

公式リファレンスはこちら(angular.element)です

blogCtrlの宣言場所にidを指定しておいたので、それをセレクタで
指定してあげます。

それに対してscope()メソッドを実行することで、対象のscopeが取得できます。
つまり、blogCtrlのスコープが取得できます。

あとは、そのスコープに渡したいデータを渡すだけ。

上記のコードを利用したサンプルを作成してみました。

sample

ネタさえわかってしまえば、特別難しいことはしていません。

ポイントは

の箇所です。

angular.extend({}, user)はuserオブジェクトのcloneをしてます。
普通に代入するとcloneではなく、参照がコピーされてしまうので
編集前のuserオブジェクトを保持しておき、編集のキャンセルが
されたときに、編集前にオブジェクトを戻すためです。

これで、編集画面のviewを1つだけに、内容は選択されたオブジェクトによって
動的に切り替えています。

しかし、問題としては、本来userCtrl内の$scope.userを、viewの都合で
他のコントローラーに渡して、そこでデータを編集していることです。

これはどうなんだろう・・・・。

これに対する対応策として、僕はmodelの一部をserviceから取得して、
編集・削除などはserviceを介してリクエストを行う、ということを検討しました。
それは機会があれば、おいおい・・・。

ざっくりですが、ここまでです。

とりあえず

この2点を確認できれば、と思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です