Angular 4 ngOnInit не вызывается после router.navigate

У меня есть 3 вкладки, в которых одна вкладка показывает таблицу со списком сотрудников. Хорошо работает, когда он загружается в первый раз .ngOnInit Получает данные с сервера, используя http get. После этого, когда я нажимаю добавить нового сотрудника, чтобы открыть форму, которая принимает данные от пользователя, и когда нажимается эта отправка, я вызываю функцию, которая вызывает почтовую службу http, чтобы отправить эти данные на мой сервер, где он вставляет записи, а затем после этого. он перенаправляется обратно в компонент сотрудника, но теперь, когда компонент сотрудника уже загружен, я не вижу новую запись, вставленную в таблицу, пока не перекомпилирую свой код.

employee.component.ts (который загружает таблицу сотрудников)

import { Component, OnInit, OnDestroy } from '@angular/core';
import { EmployeeService } from '../employee.service';
@Component({
  selector: 'app-employees',
  templateUrl: './employees.component.html',
  styleUrls: ['./employees.component.css']
})
export class EmployeesComponent implements OnInit {

public employeeObj:any[] = [{emp_id:'',empname:'',joindate:'',salary:''}] ;
constructor(private employeService:EmployeeService) { }

ngOnInit() {    
this.employeService.getEmployees().subscribe(res => this.employeeObj = res);
}

}

form.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { EmployeeService } from '../../employee.service';
import { Router } from '@angular/router';

@Component({
    selector: 'app-form',
    templateUrl: './form.component.html',
    styleUrls: ['./form.component.css'],

})
export class FormComponent implements OnInit {
empform;

ngOnInit() { 
this.empform = new FormGroup({
    empname: new FormControl(""),
    joindate: new FormControl(""),
    salary: new FormControl("")
})
} 
constructor(private employeeService: EmployeeService, private router:Router) 
{ }

 onSubmit = function(user){
    this.employeeService.addEmployee(user)
    .subscribe(
        (response) => { this.router.navigate(['/employees']); }  
    );

}
}

employee.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';
@Injectable()
export class EmployeeService{
constructor(private http:Http){}
addEmployee(empform: any[]){
    return this.http.post('MY_API',empform);
}

getEmployees(){
    return 
this.http.get('MY_API').map((response:Response)=>response.json());
}
}

AppModule.ts

    import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';

import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { EmployeeService } from './employee.service';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { NavComponent } from './nav/nav.component';
import { ContainerComponent } from './container/container.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { EmployeesComponent } from './employees/employees.component';
import { CompaniesComponent } from './companies/companies.component';
import { InternsComponent } from './interns/interns.component';
import { FormComponent } from './employees/form/form.component';
import { ComformComponent } from './companies/comform/comform.component';
import { InternformComponent } from './interns/internform/internform.component';

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    NavComponent,
    ContainerComponent,
    DashboardComponent,
    EmployeesComponent,
    CompaniesComponent,
    InternsComponent,
    FormComponent,
    ComformComponent,
    InternformComponent
  ],
  imports: [    
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule,
    RouterModule.forRoot([
            {
                path:'dashboard',
                component:DashboardComponent
            },
            {
                path:'employees',
                component:EmployeesComponent
            },
            {
                path:'companies',
                component:CompaniesComponent
            },
            {
                path:'interns',
                component:InternsComponent
            },
            {
                path:'addemployee',
                component:FormComponent
            },
            {
                path:'comform',
                component:ComformComponent
            },
            {
                path:'internform',
                component:InternformComponent
            }       
      ])
  ],
  providers: [EmployeeService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Проблема в том, что я вызываю мой API из ngOnInit, который прекрасно загружается при первой загрузке компонента. Когда я отправляю форму, она отправляется в мой API, а затем перенаправляется обратно в компонент сотрудника, но данные не обновляются, как следует.

PS: прошу прощения за такой небольшой пост. Я новичок на этом сайте.

Обновить:

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

Самая важная концепция для адаптации здесь - это угловые крючки жизненного цикла. Что происходит, мы вызываем ngOnInit при первой загрузке компонента, и он срабатывает только один раз, когда угловое приложение загружается. Это похоже на конструктор класса, но срабатывает только один раз. Таким образом, вы не должны помещать здесь какие-либо модификации, связанные с DOM. Вы должны понимать угловые крючки жизненного цикла, чтобы решить эту проблему. У меня нет рабочего решения, поскольку я переехал в Vuejs с последних 8 месяцев, но в свободное время я опубликую обновление здесь.

Ответ 1

Попробуйте добавить событие router в компонент employee. Чтобы каждый раз, когда состояние URL-адреса /employee маршрутизировано, оно будет получать сведения о сотрудниках.

employee.ts компонент

constructor(private employeeService: EmployeeService, private router:Router) 
{ }

ngOnInit() {    
  this.router.events.subscribe(
    (event: Event) => {
           if (event instanceof NavigationEnd) {
                this.employeService.getEmployees().subscribe(res => this.employeeObj = res);
           }
    });
}

Ответ 2

Как правило, при маршрутизации маршрутизатор angular повторно использует один и тот же экземпляр компонента, если это возможно.

Итак, например, переход от /component/1 в /component/2, где URL-адрес сопоставляется с одним и тем же компонентом (но с разными параметрами), приведет к тому, что маршрутизатор создаст экземпляр компонента, когда вы перейдете к /component/1, а затем повторно использовать тот же самый экземпляр, когда вы переходите к /component/2. Основываясь на том, что вы описываете (где ngOnInit только вызывается один раз), кажется, что это то, с чем вы сталкиваетесь. Трудно сказать наверняка, не видя шаблонов и конфигурации вашего маршрута. Я знаю, что вы говорите, что ваш URL-адрес меняется с /employees на /form, но это может быть неважно, в зависимости от того, как настроены ваши шаблоны и настройка маршрута. Вы можете опубликовать этот код (ваши шаблоны и конфигурацию маршрутизатора) здесь для проверки, если хотите.

Запрет на то, что другой вариант заключается в том, что маршрутизатор предоставляет все свои события в виде потока. Таким образом, вы можете подписаться на этот поток и действовать по этому поводу, а не просто полагаться на ngOnInit.

В вашем employee.component.ts

.....
export class EmployeesComponent implements OnInit {

.....

ngOnInit() {


   this.router.events
              // every navigation is composed of several events,
              // NavigationStart, checks for guards etc
              // we don't want to act on all these intermediate events,
              // we just care about the navigation as a whole,
              // so only focus on the NavigationEnd event
              // which is only fired once per router navigation
              .filter(e => e instanceof NavigationEnd)
              // after each navigation, we want to convert that event to a call to our API
              // which is also an Observable
              // use switchMap (or mergeMap) when you want to take events from one observable
              // and map each event to another observable 
              .switchMap(e => this.employeeService.getEmployees())
              .subscribe(res => this.employeeObj = res);    
}

EDIT

Я вижу один фрагмент странного кода:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { EmployeeService } from '../../employee.service';
import { Router } from '@angular/router';

@Component({
    selector: 'app-form',
    templateUrl: './form.component.html',
    styleUrls: ['./form.component.css'],

})
export class FormComponent implements OnInit {
  empform;

  ngOnInit() { 
    this.empform = new FormGroup({
      empname: new FormControl(""),
      joindate: new FormControl(""),
      salary: new FormControl("")
    })
  } 

  constructor(private employeeService: EmployeeService, private router:Router) { }

 onSubmit(user){   // <--  change this line
    this.employeeService.addEmployee(user)
    .subscribe(
        (response) => { this.router.navigate(['/employees']); }  
    );

  }
}

Но в целом вы говорите, что если вы переходите к компоненту своего сотрудника, а затем к компоненту формы, а затем возвращаетесь к компоненту своего сотрудника, когда вы нажимаете на компонент employee во второй раз, ваш список сотрудников не обновляется.

Можете ли вы использовать операторы console.log, чтобы гарантировать, что ngOnInit вызывается несколько раз в вашем потоке экрана выше? Поскольку, основываясь на конфигурации вашего маршрутизатора, когда вы переходите к списку сотрудников и формируетесь, ваш компонент сотрудника должен быть повторно инициализирован (снова вызвав ngOnInit)

Ответ 3

Когда ваш компонент связан с маршрутом, лучше добавить свой код в конструктор, который подписывается на параметры ActivatedRoute и форсирует обнаружение изменений, например:

constructor(private route: ActivatedRoute, private changeDetector: ChangeDetectorRef) {
    super();
    this.route.params.subscribe((data) => {
    */update model here/*
    this.changeDetector.detectChanges();
   } 
}

Ответ 4

Если вы понижаете рейтинг @ angular/[email protected], похоже, работаете там, где на routerLink, если вы перемещаете его, будет вызываться ngOnInit

Ответ 5

Убедитесь, что у вас есть <route-outlet></route-outlet> внутри app.component.html. Это должно отлично работать с последней версией Angular 5.

Ответ 6

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

Сначала проверьте, что ваш журнал показывает что-то вроде этого:

WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?'

Если это так, решение действительно простое, вы должны указать Angular вызвать вашу директиву маршрутизации в их жизненном цикле.

Следующий код должен исправить вашу проблему:

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

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

 onSubmit = function(user) {
   this.employeeService.addEmployee(user)
     .subscribe(
       (response) => { 
         this.ngZone.run(() =>
           this.router.navigate(['/employees']));
       }  
     );
}

Ответ 7

Компонент 1.import, по которому нужно перемещаться

например. import { SampleComponent} from './Sample.component';

2. Добавить компонент к конструктору для навигации

constructor( private Comp: SampleComponent){}

3. Добавьте этот код, где вам нужно перемещаться

this.Comp.ngOnInit();
this._router.navigate(['/SampleComponent']);--/SampleComponent-your router path

напр., после сотрудника Вставьте его перенаправляет на страницу списка сотрудников

 this.service.postData(Obj)
          .subscribe(data => {
            (alert("Inserted Successfully"));
            this.Comp.ngOnInit();
            this._router.navigate(['/SampleComponent']);
          },
            error => {
              alert(error);
          });

Ответ 8

Попробуйте: в вашем компоненте конструктора employee добавьте следующее.

constructor(private employeService:EmployeeService) {
    this.ngOnInit();
}

Если это сработает, вы можете сделать что-то более элегантное. Дайте мне знать.