Не удается прочитать значение undefined, когда компоненты обмениваются данными?

Я не могу заполнить свою форму данными, полученными мной из метода getbyId() из службы, в моей консоли я вижу, что ошибки: невозможно прочитать truckId неопределенного, каждое найденное решение говорит, что моя форма отображается быстрее, чем объект, который я хочу получить с помощью метода getById(), и решение должно быть * ngIf = "грузовик", который должен сделать форму ожидания, но она не решает ее, просто отказывается отображать форму, которая принадлежит всем. IN stackblitz ниже https://stackblitz.com/edit/stackoverflow-49847806-kdjhdc?file=app%2Fservices%2Ftruck.service.ts

Но в консоли я могу видеть URL-адрес, и когда я его открываю, я вижу, что он действительно получил детали из моей внутренней службы

getTruckById(id: number): Observable<Truck> {
   const url = '${this.baseUrl}/${id}';
    return this.http.get(url, {headers: this.headers})
      .pipe(map(this.extractData),
        tap(data => console.log(JSON.stringify(data))),
        catchError(this.handleError));
  } 

Это компонент редактирования полностью

export class EditTruckComponent implements OnInit {
  five : number = 5;
  seven: number = 7;

 @Input() truck: Truck;

  truckIdTOUpdate: number;
  processValidation = false;
  dates: string;
  statusCode: number;
  requestProcessing = false;

   truckForm = new FormGroup({
    truckCode: new FormControl(Validators.maxLength(this.seven), Validators.minLength(this.five)),
    date: new FormControl('', Validators.required  ),
    descriptions: new FormControl(Validators.maxLength(this.seven), Validators.minLength(this.five))
  });


  constructor( private route: ActivatedRoute, private truckService: TruckService, private router: Router) {
  }

  ngOnInit() {
     this.getTruckDetail();
  }

  back() {
    this.router.navigate(['/trucks'])
  }

  getTruckDetail() {
    const truckId = +this.route.snapshot.paramMap.get('truckId');
   this.truckService.getTruckById(truckId)
      .subscribe((truck) => this.truck = truck)
      console.log("this is the truck" + this.truck);
  }

  processForm() {
    this.processValidation = true;
    if (this.truckForm.invalid) {
      return; //Validation failed, exit from method.
    }
    // if we are here then all good
    this.preProcessConfigurations()

    let truckCode = this.truckForm.get('truckCode').value.trim();
    let date = this.truckForm.get('date').value.trim();
    let description = this.truckForm.get('descriptions').value.trim();

    if (this.truck.truckId == undefined) {
      let truck = new Truck(null, truckCode,  date , description);

      this.truckService.createTruck(truck).subscribe((truck) => {
        console.log(truck)
        this.router.navigate(['/trucks']);
      }, errorCode => this.statusCode = errorCode);

    } else {
        this.truck = new Truck(this.truck.truckId, truckCode, date, description);
      this.truckService.updateTrucks(this.truck).subscribe((truck)=> {
        console.log(truck);
        this.router.navigate(['/trucks']);
      }, errorCode => this.statusCode = errorCode);
    }
  }

  //Perform preliminary processing configurations
  preProcessConfigurations() {
    this.statusCode = null;
    this.requestProcessing = true;
  }

}


   class="btn btn-light"
           title="Save Truck"
           data-toggle="tooltip"
           data-placement="bottom">
          <i class="fa fa-save"></i> <span class="d-none d-sm-inline" *ngIf="truck?.truckId ==undefined">Save</span>
          <span class="d-none d-sm-inline" *ngIf="truck?.truckId">Update</span>
        </a></li>
    </ul>
  </nav>
</header>

<section id="department">
  <div class="container-fluid">
    <div class="row">
      <div class="col">
        <div class="card">
          <div class="card-body">

            <form [formGroup]="truckForm" (ngSubmit)="processForm()"   id="editFormTruck" >
              <!--truck code-->
              <div class="form-group">
                <label class="form-control-label"
                       for="truckCode"></label>
                <input formControlName="truckCode"
                       id="truckCode"
                       class="form-control"
                       type="text"

                       name="truckCode"
                       min="2018-04-11" required
                       [(ngModel)]="truck?.truckCode"/> Truck Code
                <div class="alert alert-danger" role="alert"  *ngIf="truckForm.get('truckCode').invalid && processValidation" required="required" [ngClass] ="'error'">
                  you must have a minimum of 5 chars and maximum of 7
                </div>
                <div *ngIf="statusCode === 409" [ngClass] = "'success'" class="alert alert-danger" role="alert">
                  Truck with such Code already exists try another TruckCode.
                </div>

              </div>

              <!--purchasedDate-->
              <div class="form-group" >
                <label class="form-control-label"  *ngIf="truckForm.get('date').invalid && processValidation"  [ngClass] ="'error'"
                       for="purchasedDate">date is required.</label>
                <input formControlName="date"
                       id="purchasedDate"
                       class="form-control"
                        type="date"
                        name="purchasedDate"
                       [(ngModel)]="truck?.purchasedDate "
                /> Purchased Date
              </div>

Я опубликовал все, потому что неопределенное значение начинается с моей кнопки сохранения и обновления, когда я удаляю их, он переходит на truckCode, не определен

Для лучшего понимания это мой truckComponent, который перемещается в EditTruckComponent. MY truckComponent отображает список грузовиков, а также редактирует и удаляет функции теперь в моей функции редактирования в html. У меня есть только ссылка маршрутизатора

<tr *ngFor="let truck of trucks | async">
              <td>{{truck.truckId}}</td>
              <a routerLink="/truckProfile/">
              <td>{{truck.truckCode}}</td>
              </a>
              <td>{{truck.purchasedDate | date: 'yyyy-MM-dd'}}</td>
              <td>{{truck.descriptions}}</td>
              <td class="text-right">
                <a class="btn-sm btn-outline-secondary"
                   ngbTooltip="Edit Truck"
                   placement="top">
                  <i class="fa fa-bus"></i> <span
                  class="d-none d-md-inline" routerLink="/editsTrucks/{{truck.truckId}}"  >Edit</span></a>

                 <span data-toggle="modal" data-target="#deleteDialog">
                                <a href="#" class="btn-sm btn-outline-secondary"
                                 ngbTooltip="delete truck"
                                 placement="top">
                                    <i class="fa fa-remove"></i>
                                <span class="d-none d-md-inline"  (click)="deleteTruck(truck)">Delete</span></a>
                </span>
              </td>

Так что я просто делаю навигацию с помощью ссылки на маршрутизатор и на моем editTruckCompnent im, который делает getById для init

Ответ 1

Проблема была в моем java-контроллере

 @GetMapping(value = "/trucks/{truckId}")
    @ResponseStatus(HttpStatus.OK)
    public final TruckDto getTruckId(@PathVariable(value = "truckId")
                                         final Integer truckId) {

        LOGGER.debug("test: truckId({})", truckId);
        Truck truck = truckService.getTruckById(truckId);
        return mappingService.map(truck, TruckDto.class);
    }

когда я добавил эту аннотацию, она сработала. @ResponseBody. Тело ответчика сообщает контроллеру, что возвращаемый объект должен быть сериализован в JSON и передан обратно в объект HttpResponse. Вот почему я получал HttpResponse Failure

Ответ 2

Это проблема дизайна. На мой взгляд, правильный способ сделать это:

EditTruckComponent parent должен быть умным, выполнить HTTP-вызов и передать грузовик в EditTruckComponent (вы можете использовать async, чтобы не было необходимости подписываться и отписаться вручную)

Вот ключ к тому, как я представляю родительский компонент:

<app-edit-truck [truck]="truck$ | async"></app-edit-truck>

export class EditTruckParentComponent {
    truck$: Observable < Truck > ;

    constructor(private truckService: TruckService) {
        this.truck$ = this.truckService.getTruckById(truckId);
    }
}

Сделайте EditTruckComponent немым, никакими служебными вызовами и только входы и выходы. Внедрите OnChanges, чтобы обрабатывать изменения входного сигнала на грузовике и исправлять значения формы.

Компонент edit truck будет выглядеть так:

export class EditTruckParent implements OnChanges {
    @Input() truck: Truck;
    constructor() {
    }

    ngOnChanges() {
        this.truckForm.patchValue(truck);
    }
}