Місце розташування AngularJS $ не змінює шлях


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
@JimG. це не дублікат, це питання 4 роки тому, той, на який ви посилаєтесь, - 2 роки тому.
Кастро Рой

Відповіді:


298

У мене була подібна проблема кілька днів тому. У моєму випадку проблема полягала в тому, що я змінив речі за допомогою сторонньої бібліотеки (щоб бути точним jQuery), і в цьому випадку, навіть якщо виклик функцій та встановлення змінних робіт Angular не завжди визнає, що є зміни, тому він ніколи не перетравлюється.

$ apply () використовується для виконання виразу в кутовій частині ззовні кутової рамки. (Наприклад, з подій DOM браузера, бібліотеки setTimeout, XHR або сторонніх бібліотек).

Спробуйте скористатися $scope.$apply()відразу після того, як ви змінили місцеположення та зателефонували, replace()щоб повідомити Angular, що все змінилося.


1
Працює як шарм. Я додав код, який я використав до вашого допису, щоб він працював :) Дякую тобі !!!
мацько

4
Щоб отримати краще уявлення про те, як $ application працює з кутовим і як вирішити його проблеми, ось посилання для цього yearofmoo.com/2012/10/…
матсько

2
@Skeater Ви можете просто ввести кореневу область і працювати над нею так: factory ('xyz', ['$ rootScope', функція ($ rootScope) {...}])
F Lekschas

4
можна обернути зворотний виклик $ timeout, і область буде належним чином застосована
JasonS

7
Як сказав JasonS, використовуйте $ timeout (function () {// застосувати зміни тут}); Це має дві переваги: ​​1) Вам не потрібен доступ до $ range. 2) Вам не доведеться турбуватися про те, що $ застосувати alredy run. З другої причини, використання $ timeout часто є кращим підходом.
ArneHugo

56

Замість того, $location.path(...)щоб змінити або оновити сторінку, я скористався сервісом $window. У Angular ця послуга використовується як інтерфейс до windowоб'єкта, а windowоб’єкт містить властивість, locationяка дозволяє обробляти операції, пов'язані з розташуванням або URL-адресами.

Наприклад, window.locationви можете призначити нову сторінку, наприклад:

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

Або оновіть його так:

$window.location.reload();

Це працювало для мене. Це трохи відрізняється від очікуваного, але працює на дану мету.


3
я також $ location.path () не переспрямовує, коли в URL-адресі є параметри
Sudhakar

2
Це правильна відповідь. Дивіться тут
Ірвінг

28

У мене була ця сама проблема, але мій дзвінок до $ location був ВЖЕ в межах дайджесту. Виклик $ apply () просто дав дайджест $, який вже є помилкою процесу.

Цей трюк спрацював (і обов’язково $locationвведіть у свій контролер):

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

Хоча поняття не маю, для чого це було потрібно ...


5
Nooo це погана ідея. Просто перевірте, чи є фаза в межах дайджесту, і тоді ви можете пропустити застосування. Angular наздожене його та змінить URL самостійно: coderwall.com/p/ngisma
matsko

3
тайм-аут здається мені брудним злом. Якщо ваш href містить "#", $ location.path () не працює, як очікувалося. Просто видаліть повністю href = "#" у своєму тезі або просто встановіть href = "", і вам не потрібно буде використовувати $ timeout
Shankar ARUL - jupyterdata.com

7
$$ фаза - це приватна змінна, до якої не слід намагатися отримати доступ, оскільки вона може змінитися у новій версії angularjs.
Блейз

7
Використання $ timeout може бути злому, але використання $$ фази - це ще більший хак. Як правило, не переглядайте і не торкайтеся нічого, що має префікс за допомогою $$.
nilskp

3
Приблизно через 10 годин розбиття випадкових речей ... це рішення працювало на мене!
Шейкель

6

Мені довелося вбудувати свою $location.path()заяву так, оскільки мій дайджест ще працює

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

1
Дякую за функцію, дуже корисно!
Білл Еффін Мюррей

для мене проблема полягала в тому, що ми використовували angular-block-ui, і це перешкоджало оновленню місця розташування адресного рядка. ми прикрасили запит $ http булом, який наш запитFilter підібрав, щоб block-ui не запустив цей конкретний виклик, і тоді все було добре.
матао

2

У моєму випадку проблема полягала в тому, що в конфігурації шаблону відсутній необов'язковий індикатор параметра ('?').

Наприклад:

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


$location.path('/abc');

Без характеру допиту маршрут очевидно не змінився б, придушивши параметр маршруту.


Це не конфігурація шаблону, а конфігурація маршруту.
Пьотр Доброгост

1

Якщо хтось із вас використовує маршрутизатор Angular-ui / ui, використовуйте: $state.go('yourstate')замість $location. Це зробило трюк для мене.


0

Це вроджує мене (в CoffeeScript)

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

0

На мою думку, багато відповідей тут здаються трохи хиткими (наприклад, $ apply () або $ timeout), оскільки возитися з $ apply () може призвести до небажаних помилок.

Зазвичай, коли $ location не працює, це означає, що щось не було реалізовано кутовим шляхом.

У цьому конкретному питанні проблема, здається, полягає у невугловій частині AJAX. У мене була подібна проблема, коли перенаправлення з використанням $ location повинно відбуватися після того, як обіцянка вирішена. Я хотів би проілюструвати проблему на цьому прикладі.

Старий код:

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

Примітка: taskService.createTask повертає обіцянку.

$ q - кутовий спосіб використання обіцянок:

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

Використання $ q для вирішення обіцянки вирішило проблему перенаправлення.

Детальніше про послугу $ q: https://docs.angularjs.org/api/ng/service/ $ q


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

це повинно вирішити вашу проблему.


1
Запуск не встановленого часу є дуже поганою ідеєю. І, як @matsko сказав вище, $ timeout - не найкраща ідея.
gonzofish
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.