Reputation: 11
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"}
Upvotes: 1
Views: 1413
Reputation: 11
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
Upvotes: 0
Reputation: 4880
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:
Upvotes: 0
Reputation: 718
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
Upvotes: 2