0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OnsenUIでバインドが反映されない時の解決方法

Last updated at Posted at 2022-03-24

#はじめに
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回のみで、何度保存をしてもデータを反映させることが出来た。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?