Why am I not receiving the requisition data?

Asked

Viewed 112 times

1

I have an Angular frontend application consuming an Laravel API. I’ve never had problems like this in other cases. But when I try to update a record, it just doesn’t send the data to Laravel. But if I change the route and put in the insertion route works normal, send to the application an icon and a name of a subject, but sometimes you can register without icon. Follows the service class of Angular, the subjectService:

import { Injectable } from '@angular/core';
import { DefaultService } from '../default/default.interface';
import { environment } from 'src/environments/environment';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class SubjectService implements DefaultService {
  url = `${environment.url_api}/subject`;
  constructor(private http:HttpClient) { }

  public store(data:{name:string, icon?:any}):Observable<any>{
    return this.http.post(`${this.url}/`, this.structuredData(data));
  }
  public getAll():Observable<any>{
    return this.http.get(`${this.url}/`).pipe(
      map(
        (response:any) => response.data
      )
    );
  }
  public getById(id :number):Observable<any>{
    return this.http.get(`${this.url}/${id}`).pipe(
      map(
        (response:any) => response.data
      )
    );
  }
  public update(id:number, data:{name:string, icon?:any}):Observable<any>{
    console.log(this.structuredData(data));
    
    return this.http.put(`${this.url}/${id}`, this.structuredData(data));
  }

  public structuredData(data:{name:string, icon?:any}) : any {
    const formData: FormData = new FormData();
    formData.append('name', data.name);
    if(data.icon !=undefined && data.icon !=null) formData.append('icon', data.icon, data.icon.name);
    return formData;
  }
} 

The form looks like this:

<div id="modal1" class="modal modal-fixed-footer">
  <div class="row ">
    <form class="col s12" novalidate [formGroup]="form" autocomplete="off" (ngSubmit)="onSubmit()">
      <div class="modal-content">
        <h4>Editar assunto {{subject==null? '': subject.name}}</h4>

        <div class="row">
          <div class="input-field col m4 s12">
            <input id="name" type="text" formControlName="name">
            <label for="name" class="active">Nome*</label>
            <small *ngIf="form.get('name').invalid && form.get('name').touched" class="red-text">Este campo é
              obrigatório.</small>
          </div>
        </div>

        <div class="row">
          <div class="col m12 s12 file-field input-field ">
            <div class="btn tooltipped" data-position="bottom" data-delay="50"
              data-tooltip="Formatos aceitos: .jpg, .png, .jpeg">
              <span>Novo Ícone</span>
              <input type="file" accept="image/*" (change)="preparaUpload($event)">
            </div>
            <div class="file-path-wrapper">
              <input class="file-path {{icon_error?'ng-invalid':''}}" type="text">
            </div>

          </div>
        </div>

        <div class="row">
          <div class="col s12">
            <small>Os campos com * são obrigatórios.</small>
          </div>
        </div>

      </div>

      <div class="modal-footer">

        <!--BUTTONS-->
        <div class="row" *ngIf="showSaveButton">
          <div class="col s12">
            <button class="btn waves-effect waves-light" type="submit" [disabled]="isDisabled()">Salvar
              <i class="material-icons left">save</i>
            </button>

            <button href="#" class="btn grey waves-effect waves-light modal-action modal-close" (click)="voltar()"
              name="action">Voltar
              <i class="material-icons left">arrow_back</i>
            </button>

          </div>
        </div>
        <!--END BUTTONS-->

        <div class="row" *ngIf="!showSaveButton">
          <!--PRELOADER-->
          <div class="col s12">
            <div class="preloader-wrapper small active">
              <div class="spinner-layer spinner-green-only">
                <div class="circle-clipper left">
                  <div class="circle"></div>
                </div>
                <div class="gap-patch">
                  <div class="circle"></div>
                </div>
                <div class="circle-clipper right">
                  <div class="circle"></div>
                </div>
              </div>
            </div>
          </div>
          <!--END PRELOADER-->
        </div>
      </div>

    </form>


  </div>
  <swal #swal text="Ícone editado com sucesso" type="success" [showCancelButton]="false" [showConfirmButton]="false">
  </swal>

And the component thus :

import { Component, OnInit, ViewChild } from '@angular/core';
import { SwalComponent } from '@toverux/ngx-sweetalert2';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { SubjectService } from 'src/app/core/services/subject/subject.service';
import { SubjectClass } from 'src/app/shared/models/subject.model';
import { FormGroup, FormControl, Validators } from '@angular/forms';

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

  constructor(
    private subjectService:SubjectService,
    private router:Router,
    private route:ActivatedRoute
    ) { }

public form:FormGroup = new FormGroup({
  'name': new FormControl(null, [Validators.required, Validators.minLength(2), Validators.maxLength(191)]),
});
public showSaveButton = true;
public icon:any;
public subject:SubjectClass = null;
public id:number;

  ngOnInit() {
    $('.tooltipped').tooltip({delay: 50});
    
    $('.modal').modal({
      dismissible: false, // Modal can be dismissed by clicking outside of the modal
    }
    );
    $('#modal1').modal('open');
    this.route.params.subscribe(
      (params:Params)=>{
        this.id = params.id;
        this.subjectService.getById(params.id).subscribe(
          (subject:SubjectClass) => {
            this.subject = subject
            this.form.setValue({name:subject.name})
          }
          );
      }
    );

  }
  @ViewChild('swal') public swal:SwalComponent;

  preparaUpload(event:Event){
    this.icon = (<HTMLInputElement>event.target).files[0]
  }
  isDisabled():string{
    return this.form.valid? '': 'disabled';
  }
  onSubmit(){
    
    if(this.form.valid){
      this.showSaveButton = false;
      let data:any = this.icon == undefined ? this.form.value : {name: this.form.value.name, icon:this.icon};
      this.subjectService.update(this.id, data).subscribe(
        ()=>{
          this.swal.show();

          setTimeout(()=>{
            $('#modal1').modal('close');
            this.voltar();
          }, 3000)
      },
      ()=>{
        
        
      }
      )

    }

  }
  public voltar(){
    this.router.navigate(['assunto']);
  }
}

The Laravel Controller is like this:

public function update(Request $request, $id){
    return response()->json(['request'=>$request->all()]);
    $subject = Subject::find($id);
    if(!$subject) return response()->json(['not_found'], 404);
    if($request->hasFile('icon')) $this->rules['icon.*'] = 'file|mimes:png,jpg,jpeg';
    $validator = Validator::make($request->only('name', 'icon'), $this->rules);
    if($validator->fails())return response()->json(['validation_error'], 400);

    if($request->hasFile('icon')){
        $extension = $request->icon->getClientOriginalExtension();
        $name = "{$subject->id}.{$extension}";
        $upload = $request->icon->storeAs("subject_icons", $name);
        if(!$upload) return response()->json(['error_upload'], 400);
        $subject->icon = $name;
    }
    $subject->name = $request->input('name');
    return  $subject->save() ? response()->json(['success']):response()->json(['error'], 400);
}

I put this first Return to check what was returning in the request values. And it returns like this: inserir a descrição da imagem aqui

I honestly have no idea what’s going on.

1 answer

1


I got 'resolver' the problem. Searching on, this seems to be a bug, as reported by users on github. To 'solve', I had to change the sending method to POST, and add a field _method in the request passing the value PUT. It seems that this problem happens when sending forms multipart/form-data. I hope you help someone.
What has changed in service:

public update(id:number, data:{name:string, icon?:any}):Observable<any>{
    let newData:any = data;
    newData._method = 'PUT';
    return this.http.post(`${this.url}/${id}`, this.structuredData(newData));
  }

  public structuredData(data:{name:string, icon?:any, _method?:string}) : any {
    const formData: FormData = new FormData();
    formData.append('name', data.name);;
    if(data.icon !=undefined && data.icon !=null) formData.append('icon', data.icon, data.icon.name);
    if(data._method !=undefined && data._method !=null) formData.append('_method', data._method);
    return formData;
  }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.