AngularJS $ locationがパスを変更しない


126

フォームの送信後にページのURLを変更すると問題が発生します。

これが私のアプリの流れです:

  1. ルートが設定され、URLが何らかのフォームページに認識されます。
  2. ページの読み込み、コントローラーセットの変数、ディレクティブが発生します。
  3. AJAXを使用して特別なフォーム送信を実行する特別なフォームディレクティブが起動されます。
  4. AJAXが実行された後(AngularはAJAXを処理しません)、コールバックが発生し、ディレクティブが$scope.onAfterSubmit場所を設定する関数を呼び出します。

問題は、場所を設定した後に何も起こらないことです。ロケーションパラメータ/も同様に設定しようとしました...いいえ。また、フォームを送信しないようにしました。何も機能しません。

コードがonAfterSubmit関数に到達するかどうかを確認するためにテストしました(実行されます)。

私の唯一の考えは、(ディレクティブから呼び出されたために)関数のスコープが何らかの方法でonAfterSubmit変更されたということですが、スコープが変更された場合、どのように呼び出すことができますか?

これが私のコードです

var Ctrl = function($scope, $location, $http) {
  $http.get('/resources/' + $params.id + '/edit.json').success(function(data) {
    $scope.resource = data;
  });

  $scope.onAfterSubmit = function() {
    $location.path('/').replace();
  };
}
Ctrl.$inject = ['$scope','$location','$http'];

誰かが私を助けてくれますか?



これはその1年前に作成されたことに注意してください。
matsko 2014年

もう1年間の恩恵を受けて、もう1つはより正確に受け入れられた答えを持っています。
ジムG.

1
@JimG。これは重複ではありません。この質問は4年前、リンクした質問は2年前です。
Castro Roy

回答:


298

先日も同様の問題がありました。私の場合の問題は、サードパーティのライブラリ(正確にはjQuery)で変更したことです。この場合、関数の呼び出しと変数の設定が機能しても、Angularは常に変更があることを認識しないため、ダイジェストされません。

$ apply()は、角度フレームワークの外側から角度で式を実行するために使用されます。(たとえば、ブラウザのDOMイベント、setTimeout、XHR、またはサードパーティのライブラリから)。

$scope.$apply()場所を変更し、変更replace()があったことをAngularに知らせるために呼び出した直後に使用してみてください。


1
魅力のように機能します。私はそれを機能させるためにあなたの投稿に使用したコードを追加しました:)どうもありがとうございました!!!
matsko

4
$は角とどのようにそれの問題を回避するにして作品を適用する方法の良いアイデアを得るために、ここではそのためのリンクですyearofmoo.com/2012/10/...
matsko

2
@Skeaterルートスコープを挿入して、次のように操作できます:factory( 'xyz'、['$ rootScope'、function($ rootScope){...}])
F Lekschas

4
$ timeoutでコールバックをラップでき、スコープが適切に適用されます
JasonS

7
JasonSが言ったように、$ timeout(function(){//ここで変更を適用}}を使用します。これには2つの利点があります。1)$ scopeにアクセスする必要がない。2)$ apply alredyの実行について心配する必要はありません。2番目の理由により、$ timeoutを使用することが多くの場合推奨されるアプローチです。
ArneHugo 2014

56

$location.path(...)ページを変更または更新する代わりに、サービスを使用しました$window。Angularでは、このサービスはwindowオブジェクトへのインターフェースとして使用され、windowオブジェクトにはlocation、場所やURL関連の操作を処理できるプロパティが含まれています。

たとえばwindow.location、次のように新しいページを割り当てることができます:

$window.location.assign('/');

または、次のように更新します。

$window.location.reload();

それは私のために働いた。それはあなたが期待するものとは少し異なりますが、与えられた目標のために機能します。


3
私も、URLに
パラメータ

2
これが正解です。こちらをご覧ください
アーヴィング

28

同じ問題がありましたが、$ locationへの呼び出しはダイジェスト内ですでに実行されていました。$ apply()を呼び出すと、すでに処理中の$ digestにエラーが発生しました。

このトリックはうまく$locationいきました(そして必ずあなたのコントローラーに注入してください):

$timeout(function(){ 
   $location...
},1);

なぜこれが必要なのかはわかりませんが...


5
いいえ、これは悪い考えです。フェーズがダイジェスト内にあるかどうかを確認するだけで、適用をスキップできます。:アンギュラはそれに追いつくと、独自のURLを変更しますcoderwall.com/p/ngisma
matsko

3
タイムアウトは私にとって汚いハックのようです。hrefに「#」が含まれている場合、$ location.path()は期待どおりに機能しません。タグのhref = "#"を完全に削除するか、href = ""に設定すれば、$ timeoutを使用する必要はありません
Shankar ARUL-jupyterdata.com

7
$$ phaseはプライベート変数であり、新しいangularjsバージョンで変更される可能性があるため、アクセスしないでください。
ブレーズ14

7
$ timeoutの使用はハックかもしれませんが、$$ phaseの使用はさらに大きなハックです。通常、$$で始まるものを表示したり、触れたりしないでください。
nilskp 2014

3
約10時間のランダムな問題が解決した後...この解決策は私にとってうまくいきました!
Shakeel

6

$location.path()私のダイジェストがまだ実行されていたので、このようなステートメントを埋め込む必要がありました。

       function routeMe(data) {                
            var waitForRender = function () {
                if ($http.pendingRequests.length > 0) {
                    $timeout(waitForRender);
                } else {
                    $location.path(data);
                }
            };
            $timeout(waitForRender);
        }

1
機能をありがとう、とても便利です!
Bill Effin Murray、2016

私にとっての問題は、angular-block-uiを使用していて、アドレスバーの場所の更新を妨げていたことでした。$ httpリクエストを、requestFilterが取得したboolで装飾して、block-uiがその特定の呼び出しでトリガーされないようにしました。
マタオ2017年

2

私の場合、問題はテンプレート構成にオプションのパラメーターインジケーター( '?')がないことでした。

例えば:

.when('/abc/:id?', {
    templateUrl: 'views/abc.html',
    controller: 'abcControl'
})


$location.path('/abc');

問い合わせ文字がない場合、ルートは明らかにルートパラメータを抑制して変更されません。


そうではありません、テンプレートの設定が、ルート設定。
Piotr Dobrogost

1

Angular-ui / ui-routerを使用している場合は、の$state.go('yourstate')代わりにを使用してください$location。それは私のためのトリックをしました。



0

私の意見では、$ apply()をいじると不要なエラーが発生する可能性があるため、ここでの回答の多くは少しハックに見えます(例:$ apply()または$ timeout)。

通常、$ locationが機能しない場合は、角度のある方法で実装されていないことを意味します。

この特定の質問では、問題は非角度AJAX部分にあるようです。私は同様の問題を抱えていました。$ locationを使用したリダイレクトは、promiseが解決された後に行われるべきです。この例の問題を説明したいと思います。

古いコード:

taskService.createTask(data).then(function(code){
            $location.path("task/" + code);
        }, function(error){});

注:taskService.createTaskはpromiseを返します。

$ q-promiseを使用するための角度のある方法:

let dataPromises = [taskService.createTask(data)];
        $q.all(dataPromises).then(function(response) {
                let code = response[0];
                $location.path("task/" + code);
            }, 
            function(error){});

$ qを使用してpromiseを解決すると、リダイレクトの問題が解決しました。

$ qサービスの詳細:https : //docs.angularjs.org/api/ng/service/ $ q


-8
setTimeout(function() { $location.path("/abc"); },0);

それはあなたの問題を解決するはずです。


1
非setTimeoutを実行することは非常に悪い考えです。そして、@ matskoが前述したように、$ timeoutは最善のアイデアではありません。
ゴンゾフィッシュ2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.