Подтвердить что ты не робот

Angular 2 перезагрузить маршрут с изменением параметра

В настоящее время я пишу свое первое приложение Angular 2. У меня есть OverviewComponent, который имеет следующий простой шаблон:

<div class="row">
  <div class="col-lg-8">
    <router-outlet></router-outlet>
  </div>
  <div class="col-lg-4">
    <app-list></app-list>
  </div>
</div>

при обращении к URL-адресу / мой маршрутизатор перенаправляет меня на /overview, который затем загружает карту в маршрутизатор-выход. <app-list> имеет список кликаемых элементов, которые вызывают отображение <app-detail> вместо компонента приложения. Поэтому я передаю идентификатор ссылочного json файла в URL-адрес: /details/:id (на моих маршрутах).

Все вышеперечисленные работы полностью прекрасны. Если я сейчас нажму на один из элементов списка, будут показаны детали, но когда я выберу другой элемент списка, представление не изменится на новые детали. URL-адрес изменяется, но содержимое не перезагружается. Как я могу добиться повторной инициализации детали детали?

4b9b3361

Ответ 1

В соответствии с первой окончательной версией это разрешено.

Просто обратите внимание на правильное состояние reset состояния компонента при изменении параметра

this.route.params.subscribe(params => {
    this.param = params['yourParam'];
    this.initialiseState(); // reset and set based on new parameter this time
});

Ответ 2

Вы можете изменить routeReuseStrategy непосредственно на уровне компонента:

constructor(private router: Router) {

      // force route reload whenever params change;
      this.router.routeReuseStrategy.shouldReuseRoute = () => false;

}

Аналогично, стратегию повторного использования можно изменить глобально.

Это не обязательно решает вашу проблему напрямую, но, видя, как этот вопрос является первым результатом поиска для " angular 2 reload url, если изменяются параметры запроса ", это может спасти следующего человека от копания в проблемах github.

Ответ 3

Другая альтернатива, которая должна быть добавлена здесь, - предоставить RouteReuseStrategy для вашего модуля.

providers: [
  {
    provide: RouteReuseStrategy,
    useClass: AARouteReuseStrategy
  }
]

Поведение маршрутизатора по умолчанию состоит в том, чтобы повторно использовать маршрут, если конфигурация такая же (что имеет место только при изменении параметра: id в этом вопросе). Изменив стратегию, чтобы не использовать маршрут повторно, компонент будет перезагружен, и вам не нужно подписываться на изменения маршрута в компоненте.

Реализация RouteReuseStrategy может быть такой:

export class AARouteReuseStrategy extends RouteReuseStrategy {
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  store(route: ActivatedRouteSnapshot, handle: {}): void {

  }
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  retrieve(route: ActivatedRouteSnapshot): {} {
     return null;
 }
 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
   return false; // default is true if configuration of current and future route are the same
 }
}

Я тоже написал об этом здесь:

https://pjsjava.blogspot.no/2018/01/angular-components-not-reloading-on.html

Ответ 4

Я не знаю, есть ли ответ на проблему, подобную той, которую я собираюсь предложить прямо здесь, поэтому я все равно сделаю:

Мне удалось добиться "поддельной" перезагрузки следующим образом.

В основном я создавал компонент, который перенаправляет меня на "реальный" компонент, который я хочу использовать:

@Component({
  selector: 'camps-fake',
  template: ''
})
export class FakeComponent implements OnInit {

  constructor(private _router:Router,
              private _route:ActivatedRoute)
  { }

  ngOnInit() {
    let id:number = -1;
    this._route.params.forEach((params:Params) => {
      id = +params['id'];
    });

    let link:any[] = ['/details', id];
    this._router.navigate(link);
  }

}

Итак, выбрав элемент списка, маршрутизатор перейдет к /fake/:id, который просто извлекает идентификатор из URL-адреса и переходит к "реальному" компоненту.

Я знаю, что может быть более простой или более причудливый способ, но я думаю, что это решение работает очень хорошо, поскольку подделка на самом деле не привлекает внимания. Просто "мигание", когда перезагрузка страницы является негативным аспектом, но насколько мое знание css достигает, может произойти некоторый переход, чтобы покрыть это.

Ответ 5

Возможно обнаружение любых изменений в полученных параметрах, в моем случае я загружаю информацию с помощью Resolve, поэтому мне не нужен параметр (только если он изменится). Это мое окончательное решение:

public product: Product;
private parametersObservable: any;

constructor(private route: ActivatedRoute) {
}

ngOnInit() {
  this.parametersObservable = this.route.params.subscribe(params => {
    //"product" is obtained from 'ProductResolver'
    this.product = this.route.snapshot.data['product'];
  });
}

//Don't forget to unsubscribe from the Observable
ngOnDestroy() {
  if(this.parametersObservable != null) {
    this.parametersObservable.unsubscribe();
  }
}

Ответ 6

Импортируйте Router в ваш проект Angular 7.

import { Router } from '@angular/router';

Создать объект Маршрутизатора

constructor(private router: Router) {

}

Используйте routeReuseStrategy для обнаружения изменения параметров маршрутизатора

ngOnInit() {
    this.router.routeReuseStrategy.shouldReuseRoute = () => {
      // do your task for before route

      return false;
    }
}

Ответ 7

Я решил это, используя событие, если дочерний компонент отправит новую ссылку и испустит событие, тогда родитель может найти изменение и вызвать некоторую функцию перезагрузки, которая перезагрузит необходимые данные. Другой вариант - подписаться на параметры маршрута и найти, когда он изменится Но я думаю, что ребята из angular2 должны подумать о добавлении параметров в функцию router.navigate, что может заставить перезагрузить. (ForceReload = истина)

Ответ 8

надеюсь, это поможет.

constructor(private router: Router){
 // override the route reuse strategy

 this.router.routeReuseStrategy.shouldReuseRoute = function(){
    return false;
 }

 this.router.events.subscribe((evt) => {
    if (evt instanceof NavigationEnd) {
       // trick the Router into believing it last link wasn't previously loaded
       this.router.navigated = false;
       // if you need to scroll back to top, here is the right place
       window.scrollTo(0, 0);
    }
});

}

Ответ 9

В настоящее время это не поддерживается напрямую. См. Также https://github.com/angular/angular/issues/9811

Что вы можете сделать, это что-то вроде

<div *ngIf="doShow" class="row">
  <div class="col-lg-8">
    <router-outlet></router-outlet>
  </div>
  <div class="col-lg-4">
    <app-list></app-list>
  </div>
</div>
doShow:boolean: true;

constructor(private _activatedRoute: ActivatedRoute, private _router:Router, private cdRef:ChangeDetectorRef) {
  _router.routerState.queryParams.subscribe(
    data => {
      console.log('queryParams', data['st']); 
      this.doShow = false;
      this.cdRef.detectChanges();
      this.doShow = true;
  });
}

(не проверено)

Ответ 10

this.route.paramMap.subscribe(params => {
  //fetch your new parameters here, on which you are switching the routes and call ngOnInit()
  this.ngOnInit();
 });

Вам просто нужно вызвать ngOnInit() из paramMap, и он инициализирует всю страницу с недавно загруженными данными.

Ответ 11

Я не нашел, чтобы что-то из этого было хорошим и исчерпывающим решением для Angular 8. Некоторые предложения заканчивались тем, что создавали бесконечные циклы, которые приводили к переполнению стека. Другие слишком хакерские на мой вкус. Я нашел хорошее решение в Интернете, но поскольку я не могу опубликовать здесь только ссылку, я постараюсь обобщить то, что я сделал, основываясь на этой ссылке, и почему я считаю это надежным решением. Это позволяет вам просто влиять на определенные маршруты, которые требуют поведения, а не на другие, и вам не нужно накатывать какие-либо пользовательские классы, чтобы заставить его работать.

Из решения Саймона МакКлайва в https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2

Сначала измените конфигурацию вашего модуля маршрутизации приложений:

@ngModule({ imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: ‘reload})],
exports: [RouterModule] })

Затем измените маршруты, на которые вы хотите повлиять. Если вы не используете аутентификацию, вы можете опустить параметр canActivate:

export const routes: Routes = [
 {
   path: ‘invites,
   component: InviteComponent,
   children: [
     {
       path: ‘,
       loadChildren: ‘./pages/invites/invites.module#InvitesModule,
     },
   ],
   canActivate: [AuthenticationGuard],
   runGuardsAndResolvers: ‘always, //there are three options for this - see Simon post. 'Always' is the heaviest-handed and maybe more than you need.
 }
]

Наконец, обновите свой класс, чтобы он прослушивал событие навигации и действовал соответствующим образом (обязательно отмените регистрацию слушателя при выходе):

export class AwesomeComponent implements OnInit, OnDestroy{

 // ... your class variables here
 navigationSubscription;

 constructor( private router: Router ) {

   // subscribe to the router events and store the subscription so
   // we can unsubscribe later

   this.navigationSubscription = this.router.events.subscribe((e: any) => {
     // If it is a NavigationEnd event, re-initalize the component
     if (e instanceof NavigationEnd) {
       this.myInitFn();
     }
   });
 }

 myInitFn() {
   // Reset anything affected by a change in route params
   // Fetch data, call services, etc.
 }

 ngOnDestroy() {
    // avoid memory leaks here by cleaning up
    if (this.navigationSubscription) {  
       this.navigationSubscription.unsubscribe();
    }
  }
}

Ответ 12

Используйте это на вашем constructor()

this.router.routeReuseStrategy.shouldReuseRoute = () => false;