2

Let Me take famous Book Example To explain My question. I have a angular material reactive form build based on Book Model in my BookService.ts. When I change some field In this form and Submit it to my back end to update according record using Angular HttpClient PUT method It is not updating my database and comes back with and error. When I debug it, It shows ID is not defined, When I console.log(BookForm.value) I get This out put: {$key: 1234, Title: "Book Title1", Topic: "Topic1"} , No need to say my Angular HttpClient PUT Restful API needs that ID in order to be able to update that particular record in My Database table. Bellow Is My Simplified Mocked Code To Explain It.

BookModel.ts File, My Model

export interface Book{
    ID: number;
    Title: string;
    Topic: string;
}
BookService.ts File, My Service

BookForm: FormGroup = new FormGroup({
    $key: new FormControl(null),
    Title: new FormControl('', Validators.required),
    Topic: new FormControl('', Validators.required),
});


UpdateBook(bookObj: Book): Observable<Book>
{
return this.http.put<Book>(`...api/book/${bookObj.ID}`, bookObj,{
    headers: new HttpHeaders({
    'Content-Type: 'application/json'
   })
 })
}

Note: This Throw Error, ID Undefined
Book-form.component.html File

<form [formGroup] = "BookService.BookForm" class="FormCls">
 <mat-grid-list rowHeight="200px">
  <mat-grid-tile>
      <div class="form-controles-container">
        <input type="hidden" formControlName="$key" />
        <mat-form-field>
          <input formControlName="Title" matInput placeholder="Title*" />
          <mat-error>Title Needed</mat-error>
        </mat-form-field>
        <mat-form-field>
          <input formControlName="Topic" matInput placeholder="Topic*" />
          <mat-error>Topic Needed</mat-error>
        </mat-form-field>

        <div class="button-row">
          <button mat-raised-button color="primary" type="submit" (click)="onSubmit()">Submit</button>
        </div>

      </div>
  </mat-grid-tile>
 </mat-grid-list>
</form>
Book-form.component.ts File

onSubmit(): void 
{
    BookService.UpdateBook(BookService.BookForm.value).subscribe(
     b => alert(`Book Updated Successfully`),
     err => alert(`Exception While Updating: ${err}`) 
 );
}

For sure I know I need to some how convert my form value to my Book model and make sure I have that ID inside that before I pass it to my http put service. but I dont know how to do that, Im fairly new in both Angular and Typescript world and I am learning. I love reading before I ask, so went thru lots of Articles but none worked for me. For Example I tried below Article on stackoverfelow but did not work for me Reactive Forms correctly convert Form Value to Model Object

I really Appreciate you professionals and Thank For Your Time And Help.

1 Answers1

0

when you call any AbstractControl's .value method, you are gettin an object with prop: value pairs for each input in your form. As you can see, you will get an IDless object, maybe the reason is because the form has no 'ID' property, or maybe it is because the value is null (when you transform an object to JSON, all properties that have null value get deleted).

If you know the id from the HTML, you can pass it in the function <button mat-raised-button color="primary" type="submit" (click)="onSubmit(sth.id)">

if that's not the case (I think it isn't), you could add the ID before calling your service with the .patchValue({ id: idInfo }) method that any AbstractControl has (in this case, you won't need to add a hidden input, unless you add it for another reason).

Do a patch before calling the service and it should work.

I'm not sure if this is enough info to help you, feel free to ask any questions.

edit (to add a code example):

onSubmit(): void 
{
    // the lines I added
    const bf = BookService.BookForm;
    bf.patchValue({ ID: 'anyIdYouLike' });

    // what stays the same (except the bf.value shortened version)
    BookService.UpdateBook(bf.value).subscribe(
       b => alert(`Book Updated Successfully`),
       err => alert(`Exception While Updating: ${err}`) 
 );
}
  • Thank yo so much Francisco for ur answer, but as I said I am really novice in Angular, Typescript, If you dont mind would u plz tell me where should I do .patchBalue things? If you can edit your answer to include that that would be highly appriciated – CodeGoorila Apr 16 '19 at 18:20
  • and one more thing Francisco, when I consloe.log form value, I do have ID but its inside $key – CodeGoorila Apr 16 '19 at 18:23
  • i edited my comment. You have that name because your FormControlName is '$key' and that's the symbol it is using. You can change the name of the FormControl, or change the service where it says `...api/book/${bookObj.['$key']}` – Francisco Santorelli Apr 16 '19 at 18:25
  • Based on my Model I did this, but it did not work again const bf = BookService.BookForm; bf.patchValue({ ...bf, id: 'ID' }); – CodeGoorila Apr 16 '19 at 18:30
  • yeh cuz I did a mistake in the `...bf` part, you are passing a deconstructed FormGroup.. it should have been ...bf.value, but anyways, just passing the Id should also work. Try it out, although you might need to create the property first as a FormControl (not sure, have not tried), and also be wary of Caps – Francisco Santorelli Apr 16 '19 at 18:32
  • Still Not Working Fransico , even i tried passing $key since my ID is inside it but did not work.. bf.patchValue({ ID: '$key' }); – CodeGoorila Apr 16 '19 at 18:42
  • after patching also when i console.log bf.value, i see {$key: 1111, Title:"book Title 1", Topic: "Topic1"} – CodeGoorila Apr 16 '19 at 18:47
  • have you tried passing the bookObj['$key'] to the service instead of bookObj.ID? I don't understand why the formControl has a $key prop, when you want an ID prop, probably because there's more info i dont know. Try this and tell me if it works – Francisco Santorelli Apr 16 '19 at 18:52
  • it gives compile time error, dose not like .['$key] – CodeGoorila Apr 16 '19 at 18:55
  • you are lacking the other ' < ---- [ '$key' ] Also, it's without the dot: `bookObj['$key']` – Francisco Santorelli Apr 16 '19 at 18:56
  • I tried that as well with out dot .... same error, Francisco in my service side i do have bookObj.ID property but its not defined, i belive we should do that patchiValue things in my Book-Form.Component.ts part, we are missing something there, maybe a casting ? – CodeGoorila Apr 16 '19 at 19:05
  • that bookObj['$key'], Fransico let me tell u something that may ring a bell for u. in my ts file after i do ```bf.patchValue({ID:'$key'});``` OR ```bf.patchValue({ID:'ID'});``` and cast it to Book using ``` var bookVar = bf.value;``` when I pass that bookVar into my update service like ```BookService.UpdateBook(bookVar);.subscri``` I get red line under bookVar telling ID missing in Book type, I guess that patching is not working or I do something wrong – CodeGoorila Apr 16 '19 at 19:45