ビューが開かれる/表示されるたびにコントローラー関数を実行します


81

下部に3つのイオンタブがあるクラシックな3ボタンメニューを使用するangular + ionicのアプリを作成しています。ユーザーがタブをクリックすると、そのテンプレートがui-routerを介して開きます。

私はこのような状態を持っています:

$stateProvider
  .state('other', {
    url: "/other",
    abstract: true,
    templateUrl: "templates/other/other.html"
})

テンプレートでは、次のようにします。

<ion-nav-view name="other" ng-init="doSomething()"></ion-nav-view>

コントローラーにdoSomething()関数を記述して、そこで手動で呼び出すことができることを認識しています。それでも同じ問題が発生します。誰かがそのビューを開くたびに、doSomething()関数を複数回呼び出す方法を理解できないようです。

現在、doSomething()関数は問題なく呼び出されますが、そのビュー/タブがユーザーによって初めて開かれたときのみです。ユーザーがそのビューまたはタブを開くたびに(ジオロケーションを更新するために)関数を呼び出したいのですが。

それを実装する正しい方法は何でしょうか?

助けてくれてありがとう!


{{doSomething()}}を試してください?
Asik 2014年

1
問題はdoSomething()にあるのではなく、正常に起動するため、2回トリガーされないだけです。ビューを最初に開いたときは正常に実行され、2回目はキャッシュされたビューなどをロードしているように見えますか?
Jorre 2014年

ng-initは関数を1回だけ呼び出します。パーシャルビューでng-controller = "doSomething()"または{{doSomething()}}を呼び出すことができ、ルーター/パーシャルが呼び出されるたびに関数が起動されます。
asik 2014年

3
構成状態で、キャッシュをfalseに設定します。私の答えをチェックしてください。
Yakob Ubaidi 2015年

回答:


46

ビューに特定のコントローラーを割り当てている場合、ビューが読み込まれるたびにコントローラーが呼び出されます。その場合、たとえば次のように、呼び出されるとすぐにコントローラーでコードを実行できます。

<ion-nav-view ng-controller="indexController" name="other" ng-init="doSomething()"></ion-nav-view>

そしてあなたのコントローラーで:

app.controller('indexController', function($scope) {
    /*
        Write some code directly over here without any function,
        and it will be executed every time your view loads.
        Something like this:
    */
    $scope.xyz = 1;
});

編集:状態の変化を追跡し、ルートが変更されて特定のルートにアクセスしたときにコードを実行しようとする場合があります。次に例を示します。

$rootScope.$on('$stateChangeSuccess', 
function(event, toState, toParams, fromState, fromParams){ ... })

詳細については、状態変更イベントをご覧ください。


6
ありがとう、でもそれはまさに私がやっていることです。このコードは、ビューが初めてオープンエンドになったときに1回だけ実行されます。コンソールに何かを記録しようとしましたが、最初にトリガーされるだけです。
Jorre 2014年

あなたがそれがあなたのアプリで機能すると言うとき、あなたはイオンアプリについても話しているのですか?それが私にとってうまくいかない場合があるかどうかを確認しようとしています。
Jorre 2014年

2
stateChangeを操作すると、トリックが実行されます。タブをクリックするだけでも、実行は1回だけです。編集してくれてありがとう!
Jorre 2014年

これは、Ionicがアプリの特定の部分をキャッシュする方法に関係していると思います。たぶんcache-viewfalseに設定すると役に立ちますか?ionicframework.com/docs/api/directive/ionViewキャッシュビューの検索
Michael Trouw

これはおそらく、最近のionicのリリースの問題です。ただし、ルートレベルでキャッシュを無効にすることもできます。ルート構成内のすべてのルートにcache:falseを追加するだけです。
マニッシュKr。Shukla 2015

88

デフォルトでは、コントローラーはキャッシュでした。そのため、コントローラーは1回だけ起動しました。特定のコントローラーのキャッシュをオフにするには、を変更し.config(..).statecacheオプションをに設定する必要がありますfalse。例:

  .state('myApp', {
    cache: false,
    url: "/form",
    views: {
      'menuContent': {
        templateUrl: "templates/form.html",
        controller: 'formCtrl'
      }
    }
  })

詳細については、http://ionicframework.com/docs/api/directive/ionNavView/をご覧ください。


2
ログアウトコントローラーに非常に便利
mrwaim 2015

3
ionicでキャッシュがデフォルトでオンになっているのは本当に残念です。これは、デフォルトで追加するのではなく、オプトイン機能である必要があるようです。
oalbrecht 2015年

:私が使用して私は1つの状態のみを再ロードするために必要な$state.go('app.statename', {}, {reload:true});詳細はソース)。
Sjoerd Pottuit 2016

1
これは機能しますが、それを実行するための正確な方法ではありません。アプリの速度が低下します。ユーザーがそのビューに切り替えるたびにコントローラーの初期化手順全体を実行したくないと仮定すると、jczaplewの答えはより良いアプローチだと思います。
Chris Rae

素晴らしいもの。アプリ全体でキャッシュを無効にしました。私がこの答えに出くわしたことを
うれしく思い

50

AlexMartからの回答とリンクをフォローアップすると、次のように機能します。

.controller('MyCtrl', function($scope) {
  $scope.$on('$ionicView.enter', function() {
     // Code you want executed every time view is opened
     console.log('Opened!')
  })
})

3
$ionicView.beforeEnterおそらくあなたが望むものです。 「ビューが完全に入った」後に$ionicView.enter発生ます。アニメーションビュートランジションを使用している場合は、トランジションが開始$ionicView.beforeEnterするにを実行ます。これは、移行にコードを実行できることを意味します。これにより、アプリが「よりスッキリ」した感じになります。
rinogo 2016

これが最も単純でクリーンな答えだと思います。@rinogoのコメントに関しては、ビュー/コントローラーで何が起こっても、各プログラマーが「enter」と「beforeEnter」のどちらを使用するかを決めることができると思います。ここで理解しておくべき重要なことは、ビューに入るたびに関数を呼び出すライフサイクルイベントを処理できることです。
jcarballo 2017年

12

私は同じ問題に直面しました、そしてここで私は同じ問題を持つ他のすべての人にこの振る舞いの理由を残します。

ライフサイクルを見る

パフォーマンスを向上させるために、ビュー要素とスコープデータをキャッシュするIonicの機能を改善しました。コントローラが初期化されると、アプリの存続期間を通じて存続する可能性があります。それは隠され、ウォッチサイクルから削除されます。スコープを再構築していないため、ウォッチサイクルに再び入るときにリッスンする必要があるイベントを追加しました。

完全な説明と$ ionicViewイベントを表示するには、http://ionicframework.com/blog/navigating-the-changes/にアクセスしてください。


9

cache-view = "false"でビューキャッシュを無効にしてみませんか?

あなたのビューでは、これを次のようにion-nav-viewに追加します。

<ion-nav-view name="other" cache-view="false"></ion-nav-view>

またはstateProviderで:

$stateProvider.state('other', {
   cache: false,
   url : '/other',
   templateUrl : 'templates/other/other.html'
})

どちらかを選択すると、コントローラーが常に呼び出されます。


これにはパフォーマンスの副作用がありませんか?ビュー全体が毎回リロードされないように、ビューはキャッシュされていると思いました。この機能を無効にしても、ページ全体が再度読み込まれることはありませんが、コードの一部だけを再度実行する必要がありますか?
シンダルス2016

おそらく、はい@Sindarus。ただし、必要な場合がいくつかあります。私には、ビューにプラグインの描画があり、それをクリーンアップする方法がわかりませんでした。
Diogo Medeiros 2016

これは私の場合に最適なソリューションでした。ユーザーをログアウトしてからコントローラーに再度アクセスしました。キャッシュしたくないので、すべてを再初期化する必要があります。ありがとうございました!
Firas Abd Alrahman 2017年

5

たとえば、@ Michael Trouwには、

コントローラ内にこのコードを配置します。これは、この状態が開始またはアクティブになるたびに実行されます。キャッシュを無効にすることを心配する必要はなく、より良いアプローチです。

.controller('exampleCtrl',function($scope){
$scope.$on('$ionicView.enter', function(){
        // Any thing you can think of
        alert("This function just ran away");   
    });
})

ビューが表示される前に実行される$ ionicView.beforeEnter->のような柔軟性の例をさらに増やすことができます。そして、それにはさらにいくつかあります。


2

上記のビュー要素とスコープデータをキャッシュするIonicの機能を考慮すると、ビューがロードされるたびにコントローラーを実行する場合、これは別の方法である可能性があります。次の手順を実行することで、ionicで使用されるキャッシュメカニズムをグローバルに無効にできます。

$ionicConfigProvider.views.maxCache(0);

そうでなければ、私がそれを私のために働いていた方法はやっていた

$scope.$on("$ionicView.afterLeave", function () {
     $ionicHistory.clearCache();
}); 

これは、ビューを離れる前にキャッシュをクリアして、再度入力するたびにコントローラーを再実行するためです。


1

これはおそらくあなたが探していたものです:

Ionicはビューをキャッシュし、デフォルトでコントローラーをキャッシュします(最大10) http://ionicframework.com/docs/api/directive/ionView/

これらのイオンイベントに基づいてコントローラーに特定のことを実行させるためにフックできるイベントがあります。例については、ここを参照してください:http//ionicframework.com/blog/navigating-the-changes/


1
単にリンクを共有する代わりにサンプルコードを表示することで改善できます
Lawrence Weru 2015

Angular Jsにもこのようなものはありますか?
Wang'l Pakhrin 2016年

@ Wang'lPakhrinのデフォルトでは、メインコントローラー関数内で宣言して実行するコード、IIFE、または関数は、ビュー(したがってコントローラー)が読み込まれるたびに実行されます。アプリケーションの存続期間中に1回関数を実行するなどのイベントが必要な場合は、angular-ui-routerのスティッキー状態ViewContentLoadingViewContentLoadedイベントを確認してください:)
Michael Trouw 2016年

0

カメラタブを選択するとすぐにネイティブカメラをロードしようとしたときに、ionicでも同様の問題が発生しました。コントローラをカメラタブのion-viewコンポーネント(tabs.html内)に設定してから、カメラをロードする$ scopeメソッド(addImage)を呼び出すことで問題を解決しました。

www / templates /tabs.htmlで

  <ion-tab title="Camera" icon-off="ion-camera" icon-on="ion-camera" href="#/tab/chats" ng-controller="AddMediaCtrl" ng-click="addImage()">
    <ion-nav-view  name="tab-chats"></ion-nav-view>
  </ion-tab>

AddMediaCtrlで定義されたaddImageメソッドは、ユーザーが[カメラ]タブをクリックするたびにネイティブカメラをロードします。これを機能させるために、Angularキャッシュ内の何も変更する必要はありませんでした。これがお役に立てば幸いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.