Ayush Verma
Ayush Verma

Reputation: 113

Angular 7: Service not updating the page dynamically, Its getting updated after reloading the page

I am working in angular 7 I have to perform simple task there is one component teacher-details which shows the list of registered teacher in a table format (Getting this from database using node js) and also update the table when new teacher record is added, I also have a teacher.service.ts which contain teacher array and contain a method getTeacher() and addTeacher() so teacher component using this service to display the record.

My problem is when I enter new record of teacher its not getting update to the UI/page but when I reload the it gets updated, But I want to update the page dynamically as soon as I enter the record.

teacher-details.component.ts

@Component({
  selector: 'app-teacher-details',
  templateUrl: './teacher-details.component.html',
  styleUrls: ['./teacher-details.component.css']
})
export class TeacherDetailsComponent implements OnInit {

  private teachers: Teacher[] = []
  constructor(private teacherServ: TeachersService, private auth: AuthService) {
   }

  ngOnInit() {

    this.auth.getTeacherRecords().subscribe(
      res => this.teachers = res.message,
      err => console.log(err)
    ),



    this.teachers = this.teacherServ.getTeachers();
  }

}

teacher.service.ts

@Injectable()
export class TeachersService {
teacherChanged = new EventEmitter<Teacher[]>();
private teachers: Teacher[] = [];

  constructor(private auth: AuthService) {}

  getTeachers() {
    return this.teachers;
  }

  addTeachers(teacher: any) {
    this.auth.addTeacher(teacher)
    .subscribe(
      res => console.log(res),
      err => console.log(err)
    );
    this.teachers.push(teacher);
  }
}

I am also sharing my auth service which gets the details from the database.

@Injectable()
export class AuthService {

  private addTeacherUrl = "http://localhost:3000/api/addTeacher"
  private getTeacherRecordsUrl = "http://localhost:3000/api/getTeacherRecords"

  addTeacher(teacherRecord: any) {
    console.log("Inside addTEacher servvice")
    console.log(teacherRecord)
    return this.http.post<any>(this.addTeacherUrl, teacherRecord)
  }

  getTeacherRecords() {
    return this.http.get<any>(this.getTeacherRecordsUrl, {
     observe: "body" 
    })
  }
}

teacher-details.component.html

<div class="card">
  <div class="card-header border-0">
    <div class="row align-items-center">
      <div class="col">
        <h3 class="mb-0">Teacher Details</h3>
      </div>
    </div>
  </div>
  <div class="table-responsive">
    <!-- Projects table -->
    <table class="table align-items-center table-flush">
      <thead class="thead-light">
        <tr>
          <th scope="col">Teacher Name</th>
          <th scope="col">Teacher subject</th>
          <th scope="col">Teacher branch</th>
          <th scope="col">Teacher Semester</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let teachers of teachers">
          <th scope="row">
            {{teachers.fullName}}
          </th>
          <td>
            {{teachers.subject}}
          </td>
          <td>
            {{teachers.branch}}
          </td>
          <td>
            {{teachers.semester}}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

I am very confused what should I do, Please help me out here.

UPDATE:-

I did the following changes according to the suggestion:

auth.service.ts

@Injectable()
export class AuthService {

  private addTeacherUrl = "http://localhost:3000/api/addTeacher"
  private getTeacherRecordsUrl = "http://localhost:3000/api/getTeacherRecords"

   subject = new Subject<Teacher[]>();
   teachers: Teacher[] 
  constructor(private http: HttpClient) { }

  addTeacher(teacherRecord: any) {

    console.log("Inside addTEacher servvice")
    console.log(teacherRecord)
    this.teachers.push(teacherRecord)
    this.subject.next(this.teachers)
    return this.http.post<any>(this.addTeacherUrl, teacherRecord)
  }

  getTeacherRecords() {
    return this.http.get<any>(this.getTeacherRecordsUrl, {
     observe: "body" 
    })
  }
}

teacher-details.component.ts

@Component({
  selector: 'app-teacher-details',
  templateUrl: './teacher-details.component.html',
  styleUrls: ['./teacher-details.component.css']
})
export class TeacherDetailsComponent implements OnInit {

   teachers: Teacher[];
  constructor(private teacherServ: TeachersService, private auth: AuthService) {
   }

  ngOnInit() {
    this.auth.getTeacherRecords().subscribe(
      res => this.teachers = res.message,
      err => console.log(err)
    );


    this.auth.subject.subscribe(
      res => console.log(res),
      err => console.log(err)
    )
  }

}

Still data getting updated after reloading the page

Thanks.

Upvotes: 2

Views: 726

Answers (2)

Sen Alexandru
Sen Alexandru

Reputation: 2283

The getTeachers() method in your service is synchronous and will return values only when it is called.

What you probably need is a Subject that emits values whenever you tell it to. I believe something like this in your service:

import { Subject } from 'rxjs';

const subject = new Subject<Teacher[]>();

addTeacher(teacherRecord: any) {
    console.log("Inside addTEacher servvice")
    console.log(teacherRecord)
    //HERE YOU ADD THIS
    this.teachers.add(teacherRecord);
    this.subject.next(this.teachers);

    return this.http.post<any>(this.addTeacherUrl, teacherRecord)
}

and in your ts file you initialize like this:

ngOnInit() {

    this.auth.getTeacherRecords().subscribe(
      res => this.teachers = res.message,
      err => console.log(err)
    ),

    this.auth.subject.subscribe(
      res => this.teachers = res.message,
      err => console.log(err)
    ),
  }

Also, remember to unsubscribe on OnDestroy to avoid memory leaks.

Upvotes: 2

Dmitrii Samoilov
Dmitrii Samoilov

Reputation: 11

You subscribe to the getTeacherRecords() in onInit().

This method returns an observable which is not getting updated when you do something on the page because a new HTTP request is not send.

The issue is that you use an observable that does not emit other values. As I can see, you use EventEmitter in teachers service. You should subscribe to it in your component like this:

ngOnInit() {
    this.teachers = this.teacherServ.teacherChanged.subscribe(
        teachers => this.teachers = teachers
    );
  }

Note You should unsubscribe in ngOnDestroy - it's best practice.

Do not forget to emit teachers after addition:

addTeachers(teacher: any) {
    this.auth.addTeacher(teacher)
    .subscribe(
      res => console.log(res),
      err => console.log(err)
    );
    this.teachers.push(teacher);
    // note that line
    this.teacherChanged.emit(this.teachers);
  }

This should work, hope that hepls!

Upvotes: 1

Related Questions