AngularJS $ lokasi tidak mengubah jalur

126

Saya mengalami masalah dengan mengubah URL halaman setelah formulir dikirimkan.

Inilah alur aplikasi saya:

  1. Rute ditetapkan, URL dikenali ke beberapa halaman formulir.
  2. Memuat halaman, set variabel kontroler, arahan dipecat.
  3. Arahan formulir khusus dipecat yang melakukan pengiriman formulir khusus menggunakan AJAX.
  4. Setelah AJAX dilakukan (Angular tidak menangani AJAX) maka panggilan balik dipecat dan arahan memanggil $scope.onAfterSubmitfungsi yang mengatur lokasi.

Masalahnya adalah bahwa setelah mengatur lokasi, tidak ada yang terjadi. Saya sudah mencoba mengatur param lokasi /juga ... Tidak. Saya juga sudah mencoba tidak mengirimkan formulir. Tidak ada yang berhasil.

Saya telah diuji untuk melihat apakah kode tersebut mencapai onAfterSubmitfungsi (yang berfungsi).

Satu-satunya pemikiran saya adalah bahwa entah bagaimana ruang lingkup fungsi diubah (sejak dipanggil dari direktif), tetapi sekali lagi bagaimana ia bisa memanggil onAfterSubmitjika ruang lingkup berubah?

Ini kode saya

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'];

Bisakah seseorang membantu saya?

matsko
sumber
1
kemungkinan duplikat dari $ location.path Angular tidak bekerja
Jim G.
Perlu diingat bahwa ini dibuat setahun sebelum itu.
matsko
Benar dan dengan manfaat satu tahun ekstra, yang lain memiliki jawaban diterima yang lebih tepat benar.
Jim G.
1
@ Jim. ini bukan duplikat, pertanyaan ini 4 tahun yang lalu, yang Anda tautkan, 2 tahun yang lalu.
Castro Roy

Jawaban:

298

Saya memiliki masalah serupa beberapa hari yang lalu. Dalam kasus saya masalahnya adalah bahwa saya mengubah hal-hal dengan perpustakaan pihak ke-3 (jQuery tepatnya) dan dalam hal ini meskipun fungsi panggilan dan pengaturan variabel bekerja Angular tidak selalu mengenali bahwa ada perubahan sehingga tidak pernah dicerna.

$ apply () digunakan untuk mengeksekusi ekspresi dalam sudut dari luar kerangka sudut. (Misalnya dari acara DOM browser, setTimeout, XHR atau perpustakaan pihak ketiga).

Coba gunakan $scope.$apply()segera setelah Anda mengubah lokasi dan menelepon replace()untuk memberi tahu Angular bahwa segalanya telah berubah.

F Lekscha
sumber
1
Bekerja seperti pesona. Saya telah menambahkan kode yang saya gunakan ke dalam posting Anda untuk membuatnya bekerja :) Terima kasih banyak !!!
matsko
4
Untuk mendapatkan ide yang lebih baik tentang bagaimana $ apply bekerja dengan angular dan bagaimana mengatasi masalah-masalahnya, berikut ini tautan untuk yearofmoo.com/2012/10/…
matsko
2
@Skeater Anda cukup menyuntikkan lingkup root dan mengoperasikannya seperti ini: factory ('xyz', ['$ rootScope', function ($ rootScope) {...}])
F Lekschas
4
dapat membungkus panggilan balik Anda dengan $ timeout dan ruang lingkup akan diterapkan dengan benar
JasonS
7
Seperti kata JasonS, gunakan $ timeout (function () {// terapkan perubahan di sini}); Ini memiliki dua keuntungan: 1) Anda tidak perlu akses ke $ scope. 2) Anda tidak perlu khawatir tentang $ apply alredy running. Untuk alasan ke-2, menggunakan $ timeout seringkali merupakan pendekatan yang disukai.
ArneHugo
56

Alih-alih $location.path(...)mengubah atau menyegarkan halaman, saya menggunakan layanan ini $window. Di Angular layanan ini digunakan sebagai antarmuka ke windowobjek, dan windowobjek tersebut berisi properti locationyang memungkinkan Anda untuk menangani operasi yang terkait dengan hal-hal lokasi atau URL.

Misalnya, dengan window.locationAnda dapat menetapkan halaman baru, seperti ini:

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

Atau segarkan, seperti ini:

$window.location.reload();

Ini berhasil untuk saya. Ini sedikit berbeda dari yang Anda harapkan tetapi bekerja untuk tujuan yang diberikan.

Paulo Oliveira
sumber
3
saya juga, $ location.path () tidak mengalihkan ketika url memiliki params
Sudhakar
2
Ini jawaban yang benar. Lihat di sini
Irving
28

Saya memiliki masalah yang sama, tetapi panggilan saya ke $ location SUDAH dalam intisari. Memanggil $ apply () baru saja memberikan $ digest sudah dalam kesalahan proses.

Trik ini berhasil (dan pastikan untuk menyuntikkan $locationke controller Anda):

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

Meskipun tidak tahu mengapa ini perlu ...

Ross R
sumber
5
Tidaaaak ini ide yang buruk. Cukup periksa untuk memetikan fase itu dalam intisari dan kemudian Anda dapat melewati berlaku. Angular akan menyusulnya dan mengubah URL-nya sendiri: coderwall.com/p/ngisma
matsko
3
batas waktu sepertinya hack kotor bagi saya. Jika href Anda berisi "#", $ location.path () tidak berfungsi seperti yang diharapkan. Cukup hapus seluruhnya href = "#" pada tag Anda atau setel ke href = "" dan Anda tidak perlu menggunakan $ timeout
Shankar ARUL - jupyterdata.com
7
Fase $$ adalah variabel pribadi yang tidak boleh Anda coba akses karena mungkin berubah dalam versi angularjs baru.
Blaise
7
Menggunakan $ timeout mungkin merupakan peretasan, tetapi menggunakan fase $$ adalah peretasan yang lebih besar. Secara umum, jangan melihat atau menyentuh sesuatu yang diawali dengan $$.
nilskp
3
Setelah sekitar 10 jam hal-hal acak melanggar ... solusi ini berhasil untuk saya!
Shakeel
6

Saya harus menyematkan $location.path()pernyataan saya seperti ini karena intisari saya masih berjalan:

       function routeMe(data) {                
            var waitForRender = function () {
                if ($http.pendingRequests.length > 0) {
                    $timeout(waitForRender);
                } else {
                    $location.path(data);
                }
            };
            $timeout(waitForRender);
        }
Helzgate
sumber
1
Terima kasih untuk fungsinya, sangat berguna!
Bill Effin Murray
bagi saya masalahnya adalah kami menggunakan angular-block-ui dan mencegah pembaruan lokasi bilah alamat. kami menghiasi permintaan $ http dengan bool yang diambil oleh requestFilter kami sehingga block-ui tidak memicu panggilan khusus itu, dan kemudian semuanya baik-baik saja.
matao
2

Dalam kasus saya, masalahnya adalah indikator parameter opsional ('?') Hilang dalam konfigurasi template saya.

Sebagai contoh:

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


$location.path('/abc');

Tanpa karakter interogasi rute jelas tidak akan berubah menekan parameter rute.

Víctor Hugo
sumber
Ini bukan konfigurasi template tetapi konfigurasi rute.
Piotr Dobrogost
1

Jika ada di antara Anda yang menggunakan router Angular-ui / ui, gunakan: $state.go('yourstate')sebagai ganti $location. Itu berhasil bagi saya.

Elferone
sumber
0

Ini bekerja untuk saya (dalam CoffeeScript)

 $location.path '/url/path'
 $scope.$apply() if (!$scope.$$phase)
Fangxing
sumber
0

Menurut pendapat saya, banyak jawaban di sini tampaknya sedikit macet (misalnya $ apply () atau $ timeout), karena bermain-main dengan $ apply () dapat menyebabkan kesalahan yang tidak diinginkan.

Biasanya, ketika $ location tidak berfungsi itu berarti ada sesuatu yang tidak diimplementasikan secara angular.

Dalam pertanyaan khusus ini, masalahnya tampaknya di bagian AJAX non-sudut. Saya punya masalah serupa, di mana pengalihan menggunakan $ lokasi harus dilakukan setelah janji terselesaikan. Saya ingin menggambarkan masalah pada contoh ini.

Kode lama:

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

Catatan: taskService.createTask mengembalikan janji.

$ q - cara sudut untuk menggunakan janji:

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

Menggunakan $ q untuk menyelesaikan janji memecahkan masalah pengalihan.

Lebih lanjut tentang layanan $ q: https://docs.angularjs.org/api/ng/service/ $ q

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

itu harus menyelesaikan masalah Anda.

Akshay
sumber
1
Menjalankan non-setTimeout adalah ide yang sangat buruk. Dan, seperti @matsko katakan di atas, $ timeout bukanlah ide terbaik.
gonzofish