Problem with Http post Angularjs2

2

I followed the forms tutorial in the Angularjs2 documentation, but I can not send it by the post method

I created the class as in the example

export class Hero {
   constructor(
     public id: number,
     public name: string,
     public power: string,
     public alterEgo?: string
   ) {  }
}

Then I call her in this way

    this.hero = new Hero(42, 'SkyDog',
                   'Fetch any object at any distance',
                   'Leslie Rollover');

And my method of saving is

    save(hero){     
  this.http.post('mi-url', hero,
    { headers: this.headers }).map(response => response.json())
    .subscribe(
        data => console.log('data', JSON.stringify(data)),
        error => console.log(JSON.stringify(error)),
        () => console.log('Completed')
    );      
}

Now, my object in the console is displayed correctly, but in laravel I am receiving an empty object, the answer it gives me is "[]", an empty object

while if I change the line and put

    this.http.post('mi-url', JSON.stringify(hero), etc etc);

I get this answer in laravel

    {"id":42,"name":"SkyDog","power":"Fetch_any_object_at_any_distance","alterEgo":"Leslie_Rollover"}: ""

I tried to solve it but I think I'm missing something out

in laravel I'm just returning the object in this way

    public function store(Request $request)
   { 
     if($request->ajax())
     {
      return $request->all();
     }             
   }
    
asked by danielvkp 19.03.2017 в 15:44
source

2 answers

4

The Angular method, post is defined as:

this.http.post(urlHaciaDondeEnviarLosDatos, datosAEnviar, cabecerasAdicionales)

Being:

  • urlHaciaDondeSendDatas the path your server listens to for the post. This you have already solved.

  • DatosAEnviar is where your questions are.

Why?

Because your frontEnd ( Angular ) is written in the JavaScript language. Whereas your backEnd ( Laravel ), is written in the PHP language.

If you want to send an object JavaScript to PHP , you can not do it directly because they are different programming languages. Therefore, do:

this.http.post(..., hero, ...)

It does not make much sense, since your hero variable is referencing a JavaScript object. Reaching Laravel an empty object ( [] ) that is the scenario you describe.

So, how to send data from one language to another?

You can easily send plain text from one language to another. Therefore one solution is to convert your object from JavaScript to Text , then send that text and receive it in Laravel. Finally, convert that Text to a PHP object.

In summary:

  • Convert Javascript Object to Text .
  • Send this text from JavaScript (Angular).
  • Receive that text with PHP (Laravel).
  • Convert Text to PHP Object .
  • But Text can be anything. The good thing is that certain text formats were standardized for the exchange of data. XML is one of them, JSON is the most simple and popular (In turn, this format is a subset of another called YAML ).

  • To convert a Object to Text to JavaScript
  • Usas:

    JSON.stringify(objeto);
    

    Therefore, when you are doing JSON.stringify(hero) , JavaScript is converting your hero object to this text:

    {
      "id":42,
      "name":"SkyDog",
      "power":"Fetch_any_object_at_any_distance",
      "alterEgo":"Leslie_Rollover"
    }
    
  • Then Angular sends this text to your server.
  • Laravel receives this. And when you show the content, you see that it is that text that you are receiving. ( Although without the spaces, of course )
  • But, if you stay there, you would be missing a step:

  • Convert that text to an object that PHP can handle.
  • You get this by using a PHP function called json_decode . So, to convert that text into a PHP Object , you could do it like this:

    $hero = json_decode($request->getContent());
    

    Saving in the variable $hero your data. So if you show with var_dump($hero); you will get:

    object(stdClass)#1 (4) { 
      ["id"]=> int(42) 
      ["name"]=> string(6) "SkyDog" 
      ["power"]=> string(32) "Fetch_any_object_at_any_distance" 
      ["alterEgo"]=> string(15) "Leslie_Rollover" 
    }
    

    And you can access a particular property by typing, for example; $hero->name that with var_dump you will see: string(6) "SkyDog"

    If you find it more convenient to convert that text to an Associative Array instead of an Object , you can use the second json_decode parameter :

    $hero = json_decode($request->getContent(), true);
    

    And now var_dump($hero); will confirm that it is an Array:

    array(4) { 
      ["id"]=> int(42) 
      ["name"]=> string(6) "SkyDog" 
      ["power"]=> string(32) "Fetch_any_object_at_any_distance" 
      ["alterEgo"]=> string(15) "Leslie_Rollover" 
    }
    

    And you can access some property by typing $hero['name']; .

    Another way, depending on your version of Laravel ( I think 5.2 + ), accounts with a method that encapsulates json_decode . The same is:

    $request->json()->all();
    

    Now, going back to the parameters of this.http.post in Angular ...

    • Additional headers will tell you Laravel that the text you are sending is in JSON format.

    You get this by writing:

    this.http.post(
      ..., 
      ..., 
      {headers: new Headers({'Content-Type': 'application/json'})}
    )
    

    Note : Headers is in import { Headers } from '@angular/http';

        
    answered by 07.08.2017 / 11:19
    source
    0

    I think you should convert the object hero to JSON and pass it as a similar parameter as you are doing directly with the object but in JSON .

    Usually I do this:

    save(hero:Hero): Observable<Boolean>{
        let _json = JSON.stringify({ hero: hero });
        let _params = "json="+_json;
        if(!environment.production && environment.depurar){
            console.log("Enviando el objeto hero para ser registrado en la base de datos");
            console.log(_params);
        }
        let _headers = new Headers({
            "Content-Type":"application/x-www-form-urlencoded",
            'Authorization': 'Bearer ' + this._autenticacionService.token
        });
        let _options = new RequestOptions({ headers: _headers });
        return this._http.post(
            environment.api_url+'/urlapifunction/hero', _params, {headers: _headers}
        ).map((response: Response) => {
                let data=this._autenticacionService.extractData(response);
                if(data.success&&data.message!=""){
                    this._helper.notificationToast(data.message,"Exito");
                }else{
                    if(data.success)
                        this._helper.notificationToast("Hero registrado","Exito");
                }
                if(data.success) return true;
                    return false;
            }).catch(err=>this._autenticacionService.handleError(err));
    }
    

    In the component which I use the service, I implement it like this:

    this._herosService.save(this.model).subscribe(
        registrado => {
            // console.log(registrado);
            if(registrado){
                this._router.navigate(['/heros']);
            }
        }
    );
    
        
    answered by 01.05.2017 в 12:14