Angular 4 ngOnInit not called after router.navigate

I have 3 tabs in which one tab shows a table with a list of employees. Works well when it loads for the first time .ngOnInit Retrieves data from the server using http get. After that, when I click add a new employee to open a form that accepts data from the user, and when this submission is clicked, I call a function that calls the http mail service to send this data to my server, where it inserts records, and then after that. it is redirected back to the employee component, but now that the employee component is already loaded, I do not see the new record inserted into the table until I recompile my code.

employee.component.ts (which loads the employee table)

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 { } 

The problem is that I call my API from ngOnInit, which loads fine the first time the component loads. When I submit the form, it is submitted to my API and then redirected back to the employee component, but the data is not updated as it should.

PS: I apologize for such a small post. I am new to this site.

Update:

It has been more than a year since I posted this thread, and I see that many people benefit from this, or maybe not. However, I would like to note that I already understood what caused the error, and now I will try to help you understand the solution.

The most important concept to adapt here is the corner hooks of the life cycle . What happens, we call ngOnInit the first time the component loads, and it only fires once when the corner application loads. It looks like a class constructor, but only fires once. Thus, you should not put here any modifications related to the DOM. You must understand the lifecycle corner hooks to solve this problem. I do not have a working solution, since I moved to Vujas from the last 8 months, but in my free time I will post an update here.

+15
source share
8 answers

Try adding a router event to the employee component. So that every time the state of the /employee url is routed, it will receive information about the employees.

employee.ts component

 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); } }); } 
+5
source

Typically, when routing, the angular router reuses the same component instance, if possible.

So, for example, switching from /component/1 to /component/2 , where the URL maps to the same component (but with different parameters), will cause the router to instantiate the component when you go to /component/1 and then reuse the same instance when you go to /component/2 . Based on what you are describing (where ngOnInit only called once), it seems like this is what you are facing. It's hard to say for sure without seeing the patterns and configuration of your route. I know that you are saying that your url is changing from /employees to /form , but that may not matter, depending on how your templates are configured and route settings. You can post this code (your templates and router configuration) here to check if you want.

The ban on the other option is that the router provides all its events as a stream. So you can subscribe to this thread and act on it, rather than just relying on ngOnInit .

In your 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

I see one piece of weird code:

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

But in general, you say that if you go to the component of your employee, and then to the component of the form, and then return to the component of your employee, when you click on the employee component for the second time, your list of employees is not updated.

Can you use console.log statements to ensure that ngOnInit is called multiple times in your screen stream above? Because, based on the configuration of your router, when you go to the employee list and form, your employee component must be reinitialized (by calling ngOnInit again)

+3
source

When your component is associated with a route, it is better to add your code to the constructor, which subscribes to the ActivatedRoute parameters and forces detection of changes, for example:

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

If you downgrade @ angular / router@4.1.3 , it seems to work where on routerLink, if you move it, ngOnInit will be called

+1
source

Make sure you have <route-outlet></route-outlet> inside app.component.html. This should work fine with the latest version of Angular 5.

+1
source

I think this happens if your routing call is outside the Angular lifecycle because you are making the asynchronous call correctly?

First, check that your log shows something like this:

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

If so, the solution is really simple, you should tell Angular to call your routing directive in their life cycle.

The following code should fix your problem:

 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'])); } ); } 
+1
source

1.import component to navigate

eg. import { SampleComponent} from './Sample.component';

2. Add a component to the constructor for navigation

 constructor( private Comp: SampleComponent){} 

3. Add this code where you need to navigate

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

e.g. after an employee Insert it redirects to the employee list page

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

Try it: add the following to your employee constructor component.

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

If that works, you can do something more elegant. Let me know.

-1
source

Source: https://habr.com/ru/post/1268474/


All Articles