Предупреждение директивы Angular 7 routerLink «Навигация запущена за пределами зоны Angular»

Я борюсь с фреймворком Angular, чтобы мое приложение работало гладко, но я не могу решить проблему с маршрутизацией. У меня есть верхний уровень AppComponent и app-routing.module.ts, которые управляют навигацией через мой пользовательский SlideMenuComponent. Мой упрощенный HTML-шаблон AppComponent:

<app-slide-menu [buttons]="menuButtons"></app-slide-menu>
<router-outlet></router-outlet>

В основе моего SlideMenuComponent лежит следующий html:

<nav><div *ngFor="let button of buttons">
    <a routerLink="{{button.routerLink}}"
    >{{button.name}}</a>
</div></nav>

Пользователь может перейти к '/courses' через это скользящее меню, которое контролируется CoursesComponent, разбивающим на страницы ссылки на определенные CourseComponent, полученные с сервера. Эти компоненты находятся в своем собственном модуле courses.module.ts со своим собственным модулем courses-routing.module.ts. Но когда я нажимаю на любую из этих ссылок, я получаю предупреждение консоли Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?, ngOnInit() не вызывается для открытого CourseCompontent и не обновляется, пока я не нажму любую из кнопок на странице. У меня возникла эта проблема при ручной навигации по router.navigate(), которая была решена путем переадресации этой задачи на NgZone.runTask(router.navigate()), но почему это происходит с тегами anchor и каталогами routerLink? Вот мой фрагмент кода CoursesComponent:

<nav><ul>
        <li *ngFor="let course of api.data | paginate: {
            currentPage: currentPage, itemsPerPage: limit, totalItems: api.total
        }">
           <a
               [routerLink]="course._id"
               [queryParams]="{ page: '1', limit: '5' }"
           >
            {{course.name}} ({{course.description}})
           </a>
        </li>
</ul></nav>

GIF для демонстрации проблемы:

введите описание изображения здесь


person Veetaha    schedule 03.11.2018    source источник
comment
Можете попробовать этот код ‹nav›‹div *ngFor=let button of buttons› ‹a [routerLink]=[button.routerLink] ›{{button.name}}‹/a› ‹/div›‹/nav›   -  person Suresh Kumar Ariya    schedule 03.11.2018
comment
@Suresh Извините, может быть, это немного вводит в заблуждение, но этот код работает нормально, это мои ссылки в меню слайдов, хотя я пытался изменить его тип интерполяции, но ничего не изменилось. Проблема возникает, когда я нажимаю <a [routerLink]="course._id" [queryParams]="{ page: '1', limit: '5' }" > {{course.name}} ({{course.description}}) </a>   -  person Veetaha    schedule 03.11.2018
comment
RouteLink должен быть определен в квадратных скобках []. [routerLink]=[курс._id].   -  person Suresh Kumar Ariya    schedule 03.11.2018
comment
@Suresh Пробовал, но без изменений. Действительно, routerLink может быть просто строкой, а не массивом путей.   -  person Veetaha    schedule 03.11.2018
comment
вместо routerlink вы можете попробовать вызвать функцию щелчка и использовать navigationByURL в качестве одного из вариантов1 или вместо относительного пути попробуйте указать абсолютный путь «/courses/id»   -  person Suresh Kumar Ariya    schedule 03.11.2018
comment
@ Суреш, да, я могу использовать это как обходной путь, но почему это происходит?   -  person Veetaha    schedule 03.11.2018
comment
Вы пробовали абсолютный путь? работает ли он?   -  person Suresh Kumar Ariya    schedule 03.11.2018
comment
@Suresh Я пробовал [routerLink]=['/courses', course._id] Но это не помогло   -  person Veetaha    schedule 03.11.2018
comment
может быть isuue с тегом привязки, кажется. если вы используете якорь, нам нужно использовать событие клика.   -  person Suresh Kumar Ariya    schedule 03.11.2018
comment
Странная проблема. Можете ли вы показать канал разбиения на страницы и как вы разрешаете api.data?   -  person Poul Kruijt    schedule 03.11.2018
comment
@PierreDuc Вот суть моего привязанного компонента работать, где я получаю курсы с сервера. Канал разбиения на страницы взят из модуля ngx-pagination npm.   -  person Veetaha    schedule 03.11.2018


Ответы (5)


Он видит ошибку, попробуйте это как обходной путь

constructor(private ngZone: NgZone, private router: Router) {}

public navigate(commands: any[]): void {
    this.ngZone.run(() => this.router.navigate(commands)).then();
}
person calebeaires    schedule 08.11.2018
comment
сработало как шарм, спасибо. какие проблемы можно ожидать от этого решения? - person Sevyls; 29.11.2018
comment
Спасибо, calebaires. Это работает и для моего случая. В моем случае это произошло при переходе на маршрут Angular7 из angularJs в приложении обновления Angular7 и AngularJs hybird. - person Rajez; 29.01.2019
comment
Это дает мне ngZone не определено - person Vincent Guyard; 06.02.2019
comment
@VincentGuyard, добавьте это в свой импорт: import { Component, OnInit, ..., NgZone} from '@angular/core'; - person Vadim; 24.07.2019
comment
В приложении может быть несколько компортов, нужно ли мне помещать данный код во все эти компоненты? - person vndpal; 26.08.2019
comment
Что касается меня, я использую push-уведомление FCM в приложении для чата Ionic, которое я создал. Когда пользователь получает уведомление, он щелкает значок, и приложение открывается, но не переходит на указанную страницу. Я пытался использовать этот метод безрезультатно. - person D.Hodges; 31.10.2019
comment
Обходной путь работает, но выглядит как взлом, и я не могу понять, в чем причина. - person Matjaz Hirsman; 04.05.2020

Мы столкнулись с этой ошибкой, когда перемещались где-то в нашем решении.

В нашем компоненте боковой панели мы используем обнаружение изменений при нажатии, и у нас был один this.ref.detectChanges(), когда произошла маршрутизация (изменение параметров), что каким-то образом нарушило маршрутизацию (возможно, выбив параллельно работающие преобразователи из ngZone или что-то подобное). После изменения этого параметра на предпочтительный в любом случае this.ref.markForCheck() эта ошибка больше не появлялась. Я рад, что нам не понадобился обходной путь, хотя поведение странное..

Надеюсь, это поможет любому, у кого есть такая же проблема.

person fberthel    schedule 21.02.2019

Поскольку принятого ответа нет, и поскольку я обнаружил, что с помощью Angular 8 ответ с самым высоким рейтингом не совсем работает и требует немного больше пояснений, я могу добавить следующее:

Моя конкретная проблема была с ag-grid, но я подозреваю, что любое место, куда внедряется компонент, внутри *ngFor или где-то еще, потенциально может вызвать эту проблему. Это очень близко к предыдущему ответу, но вместо этого объявляет строковый параметр в функции навигации, а затем вызывает navigationByUrl вместо навигации.

import { Component, NgZone } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  template: `<tag (click)="navigate(path)">clickable text</tag>`
})

constructor(private ngZone: NgZone, private router: Router) { }

public navigate(path: string): void {
  this.ngZone.run(() => this.router.navigateByUrl(path)).then();
}

Ваш пробег может отличаться, но это прекрасно сработало для меня.

person iGanja    schedule 17.02.2020
comment
Я пытаюсь это сделать в своем приложении Ionic 4 (Angular) при открытии push-уведомления, но не получаю никакого результата, по-прежнему выдает одно и то же предупреждение и застревает на главной странице, есть идеи ?? - person Hamlet Minjares; 18.02.2020
comment
@HamletMinjares - Нет идей. Вы точно следуете этой схеме? Событие (щелчок) должно вызывать функцию навигации компонента, как показано; он больше не может использовать routerLink. Кроме этого, я думаю, что это будет хорошо работать в Ionic. Я не понимаю, почему это может иметь значение, но у меня нет большого опыта работы с Ioninc. - person iGanja; 20.02.2020
comment
Я прошу прощения; Я использовал класс защиты для проверки перед вызовом этого метода и не заметил, что эта защита перенаправляется без зоны ng. Сразу после того, как я это исправил, это сработало как шарм, спасибо! - person Hamlet Minjares; 21.02.2020

Для меня эта ошибка была из-за того, что часть кода выполнялась за пределами NgZone. После чего у нас был запущен this.ref.detectChanges() для обнаружения изменений. Обнаруженные изменения изменят DOM и поставят <a [routerLink]="..."></a>. Это используется для нарушения маршрутизации. Решение: мы запустили часть кода за пределами NgZone внутри NgZone, но с использованием this.ngZone.run. Таким образом, нам не нужно было использовать ref.detectChanged(), так как измененная (подписка на RxJS Subject) находилась в NgZone. Это решило проблему маршрутизации.

Надеюсь, это поможет любому, у кого есть такая же проблема.

person Omkar    schedule 25.04.2020

Рабочий пример - обратитесь к этому

 public backButtonSubscription;
      ngAfterViewInit(): void {
        let self = this;
        this.backButtonSubscription = this.platform.backButton.subscribe(() => {
          console.log("back preseed \n \n");
    
          self._ngZone.runOutsideAngular(() => {
            setTimeout(() => {
              self.Router.navigateByUrl("/stock-management");
            }, 100);
          });
        });
      }
person Shashwat Gupta    schedule 16.07.2021