#はじめに
AngularJSとOnsenUI2系を使用してダイアログを作成した。
ダイアログの中にinputタグを挿入し、値を変更し保存するという処理。
1度目の表示(データバインド)は上手くいくが、保存後に2度目のダイアログ表示をすると、1度目の値がそのまま残ってしまう。
##現象
<template id="dialog.html">
<ons-dialog id="my-dialog">
<div style="text-align: center; padding: 10px;">
<ons-input ng-model="number"></ons-input>
<ons-button ng-click="saveNumber(number)">Save</ons-button>
</div>
</ons-dialog>
</template>
$scope.showDialog = function (index) {
// APIから数値を取得する処理
$scope.number = response[index].number
}
$scope.saveNumber = function () {
// APIに数値($scope.number)を送信する処理
$scope.number = '' // ダイアログを閉じるときに空に戻す
}
$scope.showDialogでAPIから取得した値(10)を、$scope.numberに代入し、ダイアログのinputタグに表示させる。(←問題なし)
inputで値(30)を入力しSaveボタンを押す。$scope.numberの値をAPIに渡し、保存する。(←問題なし)
再度ダイアログを開く。このとき引数のindexが変わっているため、APIから取得した値は(50)だった場合でも、ダイアログのinputタグには値(30)が残ったままになる。(←問題あり。データバインディングが反映されていない)
#試したこと
##$scope.$apply
$scope.showDialog = function (index) {
// APIから数値を取得する処理
$scope.$apply(function(){
$scope.number = response[index].number
})
}
Error: $rootScope:inprog Action Already In Progress
https://docs.angularjs.org/error/$rootScope/inprog
エラーが表示されて使えない。エラー内容を読めば、APIから値を取得している場合は$scope.$applyは使えないらしい。$timeoutが推奨されていた。
##$timeout
$scope.showDialog = function (index) {
// APIから数値を取得する処理
$timeout(function() {
$scope.number = response[index].number
}, 0)
}
エラーは消えたがデータバインディングはされず効果なし。
##ons.createDialog
OnsenUIでひとつのDOMを生成したときにデータの更新が反映されないことがあるらしい?
dialog.show()で表示するのではなく、ons.createDialogでDOMを作成することにする。
ons.createDialog('dialog.html')
$scope.showDialog = function (index) {
// APIから数値を取得する処理
$scope.number = response[index].number
}
これでは効果なし。
$scope.showDialog = function (index) {
ons.createDialog('dialog.html')
// APIから数値を取得する処理
$scope.number = response[index].number
}
showDialogの中に入れるとデータバインディングが反映された!!
しかし、これではダイアログを開くたびにDOMが増え続けることになる。
dialog.destroy()もOnsenUI2系では使用できない。
#最終的なコード
数値をオブジェクトで管理し、ダイアログを閉じるたびにオブジェクトを空にする。
<template id="dialog.html">
<ons-dialog id="my-dialog">
<div style="text-align: center; padding: 10px;">
<ons-input ng-model="dialogData.number"></ons-input>
<ons-button ng-click="saveNumber(dialogData.number)">Save</ons-button>
</div>
</ons-dialog>
</template>
$scope.dialogData = {} // ←変更:オブジェクトを定義
ons.createDialog('dialog.html')
$scope.showDialog = function (index) {
// APIから数値を取得する処理
$scope.dialogData.number = response[index].number // ←変更:オブジェクト
}
$scope.saveNumber = function () {
// APIに数値($scope.dialogData.number)を送信する処理
$scope.dialogData = {} // ←変更:ダイアログを閉じるときにオブジェクトを空に戻す
}
これでDOMの生成は1回のみで、何度保存をしてもデータを反映させることが出来た。