1

i want to send data from a twig view to a symfony controller using angular js $http method this is my javascript

<script>
var app = angular.module('app',[]);
app.controller('ctrl',function($scope,$http) {


$scope.processForm = function() {
    var val = $scope.libelle;
    $http({
        method: "POST",
        url: 'http://localhost/symangular/web/app_dev.php/home',
        headers: {
            'Content-Type': 'application/json'
        },
        data:{libelle:val}
    }).then(function (html) {
     console.log(html);


    });
}

});
</script>

and this is my controller

class DefaultController extends Controller
{
public function indexAction(Request $request)
{
    $prod = new Product();
    $form = $this->createForm(ProductType::class,$prod);
    $form->handleRequest($request);
    if($form->isSubmitted() && $form->isValid() && $request-  >isMethod('POST') && $request->isXmlHttpRequest()){
        $em = $this->getDoctrine()->getManager();
        $data = json_decode($request->getContent(), true);
        dump($request->request->get('libelle'));
        $request->request->replace($data);
        $prod->setLibelle($request->request->get('libelle'));
        $em->persist($prod);
        $em->flush();
        return new JsonResponse("good");
    }
    return $this->render('angulartestangularBundle:Default:index.html.twig',array('form'=>$form->createView()));
}

}

so when i execute i got an object in the console that i didn't understand it also i got nothing in database , did anyone have an idea about how to handle an $http angular request in symfony controller

Object {data: "<script src="https://ajax.googleapis.com/ajax/libs…: 5 }        );    })();/*]]>*/</script>↵</body>↵", status: 200, config: Object, statusText: "OK"}
1
  • 1
    Your dump() is probably polutting your Json, making it unvalid. Try removing it. Commented Apr 17, 2017 at 3:49

3 Answers 3

2

In Symfony, a request considered as a XmlHttpRequest by reading request headers. The exactly code in Symfony is:

public function isXmlHttpRequest()
{
    return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}

So, when using angularjs or any javascript framework to make a XMLHttpRequest, you should add a header with X-Requested-With key and value = XMLHttpRequest. This header also required even if you're using fetch api. In your code abow, the request call should be:

$http({
    method: "POST",
    url: 'http://localhost/symangular/web/app_dev.php/home',
    headers: {
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
    },
    data:{libelle:val}
})

If you don't want to add this header every time call $http function, you can add it as default config to $httpProvider:

angular
    .module('yourModuleName', [])
    .config(['$httpProvider', function ($httpProvider) {
        $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    }])
;

For more details about $http configs and how to set default configs, look at Angularjs Documentation

Sign up to request clarification or add additional context in comments.

Comments

0

Your approach is a little confused, and therefore very hard to debug.

its good practice (IMO) to separate your api endpoints from the controller action that renders the page. Coupling them together is going to seriously limit the extensibility of your application.

Its possible that you're failing one part of the complex if statement in your controller action; this is making it hard to debug.

Its also good practice when writing an api to provide the client with an idea of what went wrong on a call. (even if its only you accessing the api)

Looking at your code, it also looks like your getting mixed up in processing the request. Your'e validating the submission based upon it being a Product, and asking symfony to process the data on that basis, but then inside your submitted if statement, pulling out the data again..

You can still harness the symfony form validation by decoupling it and submitting this way.

/**
 * If your using annotated routing do this, or make the equivelent in your yaml file.
 * @Route("/api/product/create", name="api_product_create")
 */
public function productAction(Request $request)
{
    $data = json_decode($request->getContent(), true);

    if(!$data)
    {
         // youll want to handle this exception with a listener or somesuch so that it sends back a nice neat message to your client
         throw new InvalidArgumentException('Invalid json');
    }

    $product = new Product();
    // create your form as you did before.
    $form = $this->createForm(ProductType::class,$product);

    // this tells symfony to fill out the form, as if it was submitted conventionally.
    $form->submit($data);

    // now we can check for valid (you dont need to check submitted, as valid will do that anyway)
    if($form->isValid()) 
    {
          // persist the new object
          $em = $this->getDoctrine()->getManager();
          $em->persist($prod);
          $em->flush();

          // create a new set of return data
          $return = [
              'status' => 'success',
              'productId' => $product->getId(),
          ];

          return new JsonResponse($return, 201);
    }


      // oops, something went wrong, find out and report it
     $return = [
         'status' => 'error',
         'uri'    => $request->getPathInfo(),
         'errors' => (string) $form->getErrors(true, false),
     ];

     return new JsonResponse($return, 400);
}

then, in your template, render the url to the endpoint properly.

 url: {{ path('api_product_create') }},

this is just an example, and may not totally fit your usecase, but as you can see, once decoupled its much easier to find out what went wrong and where.

Useful resources:

Comments

0

thank you all for ansewring my question.. the informations were so helpfull .. otherwise the solution was to seprate the two actions in symfony controller and adding a request header to the $http method and it works very well .. thank u all

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.