3

I have searched a lot in stackoverflow but I don't find a real explanation to my problem.... I'm trying to make a simple angular2 application, with a RouterModule, a simple Service and a simple Component. So :
My Router Module :

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { StudentListComponent } from '../students-list.component';
import { StudentComponent } from '../student.component';

const routes: Routes = [
  { path: 'students', component : StudentListComponent },
  { path: 'student/:id', component: StudentComponent },
  { path: '**', redirectTo : '/students', pathMatch: 'full' },
  { path: '', redirectTo : '/students', pathMatch: 'full' }
];

@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})

export class AppRouterModule { }

My Component :

import { Component, OnInit } from '@angular/core';
import { StudentService } from './services/student.service';
import { Student } from './class/Student';

@Component({
  selector: 'student-list',
  templateUrl: 'app/views/students-list.component.html',
  styleUrls: ['app/views/styles/students-list.component.css'],
  providers : [ StudentService ]
})

export class StudentListComponent implements OnInit {

  private studentService: StudentService;
  students: Student[];

  constructor(studentService: StudentService) { console.log('reinit component');
    this.studentService = studentService;
  }

  ngOnInit(): void {
    if(!this.students)
      this.studentService.getStudents().then( (students) => this.students = students );
  }

}

My Service :

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Student } from '../class/Student';
import { Note } from '../class/Note';
import { CourseService } from './course.service';

@Injectable()
export class StudentService {

  static service: StudentService;

  private httpUrl = "http://localhost/NotesApp/webServ/";
  private students: Student[];
  private courseService: CourseService;
  private http:Http;

  constructor(courseService: CourseService, http:Http){ console.log('reinit service');
    this.courseService = courseService;
    this.http = http;
  }

  getStudents(): Promise<Student[]> {
        return this .http
                    .get(this.httpUrl+'getStudents')
                    .toPromise()
                    .then( response => this.hydratedStudentArray( response.json() ) )
                    .catch( this.handleError );
  }

  getStudentById(id: number): Promise<Student> {
      return this .http
                  .get(this.httpUrl+'getStudent/'+id)
                  .toPromise()
                  .then(response => this.hydratedStudent( response.json()[0]) )
                  .catch( this.handleError );
  }

  private hydratedStudentArray(jsonArray: { id: number, firstname: string, lastname: string }[]): Student[]{
    let hydratedArray: Student[] = [];

    for (let jsonElement of jsonArray){
      hydratedArray.push(new Student(jsonElement.id, jsonElement.lastname, jsonElement.firstname));
    }

    return hydratedArray;

  }

  private hydratedStudent(jsonElement: { id: number, firstname: string, lastname: string }): Student{
    return new Student(jsonElement.id, jsonElement.lastname, jsonElement.firstname);
  }

  private handleError(error: any): Promise<any> {
    console.error('An error occurred', error); // for demo purposes only
    return Promise.reject(error.message || error);
  }

}

So my problem is : When I navigate using a link like <a routerLink="/students">Students</a> or <a [routerLink]="['/student', student.id]" >{{ student.lastname }} {{ student.firstname }}</a>, this trigger the console.log I have written in the component and service constructor..., I see 'reinit component' and 'reinit service' in my console each time I navigate ... How can I avoid this ? Thanks

P.mar
  • 71
  • 2
  • 6
  • 1
    You could implement a custom reuse strategy like mentioned in http://stackoverflow.com/questions/33940095/angular2-routing-keeping-state-of-component-when-route-changes/36010817#36010817. Usually a better approach is to build the components in a way, that it doesn't matter when they are destroyed when navigating away and recreated when navigating back. For example you can store the status in a shared service instead of in the component itself. – Günter Zöchbauer Feb 17 '17 at 15:52
  • I wanted to store the students in a private property in my service, but this last become reinintialized too, like if it is not a singleton ... Are you saying this is the true functioning of angular :/ ? ... – P.mar Feb 17 '17 at 16:05
  • If you provide the service on a component, it will be created and destroyed with the component. For your use case it should be provided at a parent component (then one that contains the `` where the component is added, or provide it in `@NgModule()`, then it will be a singleton for the whole application and created and destroyed with the application. – Günter Zöchbauer Feb 17 '17 at 16:14

1 Answers1

3

The problem was here : I loaded the provider in the component itself, but it should be declared only in my NgModule, so the entire module can use it. I was re-declaring the provider in the component like this :

providers:    [ StudentService ]

and that is why the service was re-instancied each time I called the component... Thanks !

P.mar
  • 71
  • 2
  • 6