業務アプリデモ開発をベースにhifiveを学ぼう(5)「親子連携」
今回は引き続き業務アプリのデモを通じてhifiveの機能を紹介します。今回は親子連携についてです。
親子連携はいわゆる Master – Detailと呼ばれるもので、親で選んだ内容を子に伝えることで描画を更新したり、処理を行うというものになります。
今回のデモでは2つの親子連携が行われています。
ツリービューでの選択
ツリービューで項目を選択すると、右側のグリッドが更新されます。この処理は js/AppPurchaseManagerController.js に記載されています。
| '.shortcut selected': function(ctx) { | |
| : | |
| this._gridViewerController.setData(this._appLogic.searchPurchaseDatas(query)); | |
| } |
queryというのは絞り込み条件になります。それを使って js/AppPurchaseManagerLogic.js の searchPurchaseDatas を呼び出します。実際にはutil.ajaxを使っています。結果はグリッドで描画するデータの配列になります。
| searchPurchaseDatas: function(query) { | |
| return sample.util.ajax(sample.consts.url.SEARCH_WORKFLOW, query); | |
| }, |
GridViewerController.js の setData ではデータを受け取った後、描画処理を行います。ここで注意したいのは、データがPromiseオブジェクトの場合があるということです。その場合、Promiseであるかどうかを判定し( if (h5.async.isPromise(data)) { )その結果を使って再度自分自身をコールしています。これによって非同期処理でも同期のように扱えるようになります。
| setData: function(data, dummyColNums) { | |
| if (h5.async.isPromise(data)) { | |
| var indicator = this.indicator(); | |
| indicator.show(); | |
| data.done(this.own(function(d) { | |
| this.setData(d, dummyColNums); | |
| indicator.hide(); | |
| })); | |
| return; | |
| } | |
| this._gridWrapperController.setData(data, dummyColNums); | |
| this.$find('.dataLength').text(data.length); | |
| }, |
実際には js/grid/GridWrapperController.js の setData に処理を委譲しています。
| setData: function(data, dummyColNums) { | |
| this._gridController.setData(data, dummyColNums); | |
| }, |
さらに処理を js/grid/DatagridController.js に処理を渡しています。ここで実際の表示処理を行っています。画面を部品ごとに分割したり、ラッパーを挟むことで機能を分割できるようになり、メンテナンス性が維持されます。
| setData: function(data, dummyColNums) { | |
| : | |
| var dataSource = datagrid.createDataSource({ | |
| idProperty: 'id', | |
| type: 'local', | |
| param: data | |
| }); | |
| // paramを再生成する | |
| this._createDefaultParam(dummyColNums); | |
| // FIXME (0,0)にグリッドをスクロール | |
| this._gridController._viewController._vPos = 0; | |
| this._gridController._viewController._hPos = 0; | |
| this._gridController.activate(dataSource, this._param); | |
| this._gridController.search(); | |
| this._triggerLengthChange(); | |
| }, |
グリッドで選択
グリッドで行を選択した後のイベントは次のように処理されます。まず行を選択した時点で gridChangeDataSelect イベントが呼ばれます。処理を行うのは js/grid/DatagridController.js です。
| '{rootElement} gridChangeDataSelect': function() { | |
| var ids = this._gridController.getSelectedDataIdAll() | |
| this.trigger('showDetail', ids); | |
| }, |
ここでは選択されているIDを集めて、showDetailイベントを発火しています。このイベントは js/AppPurchaseManagerController.js によって監視されています。
| '.gridViewer showDetail': function(ctx) { | |
| var id = ctx.evArg; | |
| if (!id) { | |
| return; | |
| } | |
| var isMass = ($.isArray(id) ? id[0] : id).indexOf('_') === '0'; | |
| var data = this._appLogic.getPurchaseById(id); | |
| this._detailController.setData(data, isMass); | |
| }, |
そして js/DetailController.js のsetDataが呼ばれます。ここではデータを作成し、 view.updateを使って描画処理を行います。
| setData: function(data) { | |
| : | |
| var dataAry = $.isArray(data) ? data : [data]; | |
| var details = []; | |
| for (var i = 0, l = dataAry.length; i < l; i++) { | |
| var d = dataAry[i]; | |
| details.push({ | |
| id: d.id, | |
| : | |
| applicationDate: d.applicationDate | |
| }); | |
| } | |
| this.view.update('{rootElement}', 'purchaseDetail', { | |
| details: details | |
| }); | |
| this.refresh(); | |
| }, |
その他の処理
その他、画面上でボタンを押した際の処理などがありますが、いずれも実際の処理は行わずにイベントを発火しています。例えば以下は承認済みにする処理です。
| '.confirm click': function(ctx, $el) { | |
| var ids = '' + $el.data('confirm-targets'); | |
| ids = ids.split(','); | |
| if (!ids.length) { | |
| return; | |
| } | |
| if (!confirm(ids.length + '件のデータを"承認済"にします。よろしいですか?')) { | |
| return; | |
| } | |
| this.trigger('confirmPurchase', { | |
| ids: ids | |
| }); | |
| }, |
confirmPurchaseというイベントは js/AppPurchaseManagerController.js にて購読しています。
| '{rootElement} confirmPurchase': function(ctx) { | |
| var ids = ctx.evArg.ids; | |
| var promise = this._appLogic.confirmByIds(ids); | |
| this.indicator({ | |
| promises: promise | |
| }).show(); | |
| promise.done(this.own(function(datas) { | |
| this._detailController.confirmExecuted(datas); | |
| this._gridViewerController.refresh(); | |
| alert(datas.length + '件の申請を承認しました'); | |
| })); | |
| }, |
このように hifive では購読とイベントを使ってデータの伝搬と描画を行っています。その結果としてHTMLとデータ操作を分離し、メンテナンスやテストしやすいシステム構築が可能になります。
今回のコードはGitHubにアップロード されています。また、デモはこちらにて試せます。
hifiveではこのような構築法が容易になるように設計されています。ぜひお試しください。

コメントは受け付けていません。