0

I want to pass a value betwen components in order to switch from a list of candidates to another panel where i can edit the selected candidate.

Sadly, i get this error : ERROR TypeError: "this.listCandidateComponent is undefined" in my edit-candidate component when i try to log the candidate that i initialized in list-candidate component.

list-candidate.component.html

<table class="table table-striped">
  <tbody *ngFor="let candidate of candidates">
    <td><h4>{{ candidate.id }}</h4></td>
    <td><a class="btn btn-outline-warning btn-sm" style="margin: 1%"
         (click)="getCandidateById(candidate.id)" role="button">Modifier</a>
    </td>
 </tbody>
</table>

list-candidate.component.ts

@Component({
  selector: 'app-list-candidate',
  templateUrl: './list-candidate.component.html',
  styleUrls: ['./list-candidate.component.scss']
})
export class ListCandidateComponent implements OnInit {

  candidate: Candidate;
  candidates: Candidate[];

  ngOnInit() {
    this.getCandidateList();
  }

  async getCandidateById(id: number) {
    const headers = new HttpHeaders({
      'Content-type': 'application/json; charset=utf-8',
      Authorization: 'Bearer ' + this.cookie.get('access_token')
    });
    const options = {
      headers
    };
    await this.httpClient.get(`${this.baseUrl}/${id}`, options)
      .toPromise()
      .then(
        (response: Candidate) => {
          console.log('GET request successful', response);
          this.candidate = response;
        },
        (error) => {
          console.log('GET error : ', error);
        }
      );
    await this.router.navigate(['/candidates/edit']);
   }

edit-candidate.component.ts

@Component({
  selector: 'app-edit-candidate',
  templateUrl: './edit-candidate.component.html',
  styleUrls: ['./edit-candidate.component.scss']
})

export class EditCandidateComponent implements OnInit, AfterViewInit {

  candidate: Candidate;

  @ViewChild(ListCandidateComponent) listCandidateComponent;

  ngAfterViewInit() {
    this.candidate = this.listCandidateComponent.candidate;
    console.log(this.candidate);
  }

  ngOnInit() {
  }

Any ideas why ?

Triss
  • 23
  • 4
  • it is right cause u don't really know if the http request is ended at the time you read the child component property, pls write down the edit-candidate.componet.html – Vash72 May 02 '19 at 17:29
  • Doesn't async/await guarantee that the http request is ended before switching to the parent component ? – Triss May 02 '19 at 17:32
  • no, beacuse async function are async, is just the funtion to be "sync", so the this.getCandidateList(); call return a promise and resolve "later" on – Vash72 May 02 '19 at 17:34
  • edit-candidate.component.html is just a form that i would fill with the candidate i get in edit-candidate.component.ts. It's empty. – Triss May 02 '19 at 17:35
  • the "angular way" for this case is to use eventemitter and eventlistener to relate the 2 componets instead of @ViewChild, "reacting" to – Vash72 May 02 '19 at 17:36
  • ok, i re-used @ViewChild because i did previously when creating a candidate with a child component address to create both candidate and his address in the same component (and it worked :o). Will try the eventemitter then. Thx ;) – Triss May 02 '19 at 17:39
  • if the components aren't directly related, you can use a service as a "storage" to save the selected candidate, and then retrive it from the edit component – Vash72 May 02 '19 at 17:41
  • Ok, i was trying to avoid too much code but if that's a better way..:) – Triss May 02 '19 at 17:46

1 Answers1

0

You are routing to an edit page..

await this.router.navigate(['/candidates/edit']);

You can't use ViewChild in this scenario.

You have to add params to your router.navigate like

await this.router.navigate(['/candidates/edit'], { queryParams: { candidateId: id } });

and in your edit component you have to read the queryParams

id: any;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.queryParams
  .subscribe(params => {
      this.id = params['candidateId'];
  });

}

Now just load your candidate with the id in your edit component and you'r finished :)

You placed Viewchild in your edit component. If you want to load List component with viewchild, anywhere in edit-candidate.component.html has to be something like

<app-list-candidate> </app-list-candidate>

else it would always be undefined because list component is not child of edit component.

I hope it helps - sorry If I misunderstood your problem (:

Geggi632
  • 564
  • 4
  • 8