I have built a website using php and the zend framework. In one of the pages I have a zend form and a table. The user can fill in the form, click the search button(page refresh occurs) and then get the corresponding results in the table.
What I am trying to do is to implement the same functionality using Ajax so the page won't have to refresh or ask for re-submission when reloaded.
From my controller I pass the data I want to display to view.phtml.
When the page first opens all the data from database gets displayed in the table. Somehow after the user clicks search :
the ajax post data should be retrieved in the controller
compared to the rest of the data to see if there are any matches
return the data matched
public function searchAction(): ViewModel
{
$persons = $this->personsService->getAllPersons();
$form = $this->personsForm;
if ($this->getRequest()->isPost()) {
$formData = $this->params()->fromPost();
$form->setData($formData);
if ($form->isValid()) {
$validFilteredData = $form->getData();
$persons = $this->personsService->getPersonsAfterSearch($validFilteredData);
}
}
return new ViewModel([
'persons' => $persons,
'form' => $form,
]);
}
I would like any suggestions on how to implement ajax since I am a beginner in web development and I don't experience working with ajax.
Thanks in advance.
Before you do this:
return new ViewModel([
'persons' => $persons,
'form' => $form,
]);
Add this:
if ($this->getRequest()->isXmlHttpRequest()) {
return new \Zend\View\Model\JsonModel(
[
'persons' => $persons,
'form' => $form,
]
);
}
Note: you've tagged "zend-framework" but mentioned "zend3". Above solution works for ZF2 and ZF3, don't know about ZF1.
Update due to comments:
Full function would be:
public function searchAction() : ViewModel
{
$persons = $this->personsService->getAllPersons();
$form = $this->personsForm;
if ($this->getRequest()->isPost()) {
$formData = $this->params()->fromPost();
$form->setData($formData);
if ($form->isValid()) {
$validFilteredData = $form->getData();
$persons = $this->personsService->getPersonsAfterSearch($validFilteredData);
}
}
$data = [
'persons' => $persons,
'form' => $form,
];
// AJAX response
if ($this->getRequest()->isXmlHttpRequest()) {
return new \Zend\View\Model\JsonModel($data);
}
return $data; // No need to return "new ViewModel", handled via ZF magic
}
Related
I'm working on a multistep form and also there are previous buttons in that. When a user clicks the previous button they go a step back as expected, but the form is not filled with the data that is already filled in that step.
The data is stored in a session, so i thaught this wil work (in the controller):
if($this->getRequest()->isPost()) {
if ($this->getRequest()->getPost('previous')){
$data = $this->sessionContainer->PlaatsenAdvertentie;
}
else{
$data = $this->params()->fromPost();
}
$form->setData($data);
$viewModel = new ViewModel([
'form' => $form
]);
return $viewModel;
}
But no...
I made a function inside the form class:
public function populate($step,$data)
{
foreach($data['step'.$step] as $field => $value){
//uitgezond de submit en vorigestap buttons
if ($field != 'submit' && $field != 'vorigestap'){
$this->get($field)->setValue($value);
}
}
return $this;
}
I have made a form created after an Ajax request (after the first form (Test1Type) is submitted)
public function indexAction(Request $request): Response
{
$form = $this->createForm(Test1Type::class);
$form->handleRequest($request);
if ($request->isXmlHttpRequest()) {
$form = $this->createForm(Test2Type::class);
return new Response($this->renderView('test/_results.html.twig', [
'form' => $form->createView(),
]));
}
return $this->render('test/index.html.twig', [
'form' => $form->createView(),
]);
}
Then I want to submit, validate and get the datas from this Test2Type in another method
public function confirmAction(Request $request): Response
{
dump($form->getData());
return $this->render('test/confirm.html.twig', [
]);
}
But I don't have acces to my form variable and I will not re-use $form = $this->createForm(Test2Type::class);...
I think this is possible but I really don't have any clues to made this work...
Do you have some ideas ?
It's not possible, you must create $form variable before using it for submittion and validation. To avoid duplicate code on create Test2Type form, you should redirect to confirmAction in indexAction after the form submitted and valid.
public function indexAction(Request $request)
{
$form = $this->createForm(Test1Type::class)->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
return $this->redirectToRoute('confirm.action.route_name');
}
return $this->render('test/index.html.twig', [
'form' => $form->createView(),
]);
}
public function confirmAction(Request $request)
{
$form = $this->createForm(Test2Type::class)->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
return $this->render('test/confirm.html.twig', [
'data' => $form->getData()
]);
}
return $this->render('test/_results.html.twig', [
'form' => $form->createView(),
]);
}
You should add another action in your controller for the ajax request with another route!!
This is better readable code and works better with the history button of your browser. (less cache problems) furthermore you can of course simply change the 'action' attribute of the HTML <form> element. Follow this link to read how: http://symfony.com/doc/current/form/action_method.html
I want to clear session variable only when I enter my symfony form first time. In this example session is delete even when form is not valid - how can I change this?
public function dodajNewAction(Request $request, Pacjent $pacjent)
{
unset($_SESSION['test']);
$wykbad = new Wykbadpoz($pacjent);
$wykbad->setRok(date('Y'));
$wykbad->setMiesiac(date('n')); //miesiac bez zera wiodacego
$form = $this->createForm('nfz_wykbadpoz_new', $wykbad);
$form->handleRequest($request);
return [
'form' => $form->createView()
];
}
In a Symfony project you should never use superglobals like $_SESSION ($_GET, $_POST, ...). You must use the Request object.
Like this:
public function dodajNewAction(Request $request, Pacjent $pacjent)
{
$wykbad = new Wykbadpoz($pacjent);
$wykbad->setRok(date('Y'));
$wykbad->setMiesiac(date('n')); //miesiac bez zera wiodacego
$form = $this->createForm('nfz_wykbadpoz_new', $wykbad);
$form->handleRequest($request);
$session = $request->getSession();
if ($form->isValid() && $session->has('test')) {
$session->remove('test');
}
return [
'form' => $form->createView()
];
}
I'm trying to figure out how to make redirect to the same url after processing form in silex:
public function someAction(Application $app)
{
$form = ... // building form
if ('POST' === $app['request']->getMethod()) {
$form->bindRequest($app['request']);
if ($form->isValid())
{
$url = $app['url_generator']->generate(
$app['request']->get('_route'),
$app['request']->get('_route_params')
);
return $app->redirect($url);
}
}
return $app['twig']->render(
'form.html.twig',
array(
'form' => $form->createView()
)
);
}
It's possible in Symfony, but it's not working here. (Of course, i can always redirect to something like $url?success)
UPD: There's everything correct with $url. The point is that if you are trying to redirect to exactly the same url, it won't work.
The Request class has a getRequestUri() method. You can use that like this:
return $app->redirect($request->getRequestUri());
Sorry to answer your question with another question, but why would you want to redirect to the same page? The logic for your route should simply display your view after processing the form.
public function someAction(Application $app)
{
$form = ... // building form
if ('POST' === $app['request']->getMethod()) {
$form->bindRequest($app['request']);
if ($form->isValid())
{
$url = $app['url_generator']->generate(
$app['request']->get('_route'),
$app['request']->get('_route_params')
);
//return $app->redirect($url);
// just remove the return here and you're all set!
}
}
return $app['twig']->render(
'form.html.twig',
array(
'form' => $form->createView()
)
);
}
I'm really new to silex and symfony. This is my first foray into silex. I've got code that created my form in my app.php file from a little hacking and copying and pasting from documentation.
Now how do i pass this data to another page?
I would like to create a page that just dumps the post/get array to give me an idea how to pass around get/post variables.
Here's part of my app file:
<?php
/** /src/app.php */
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Register new application
*/
$app = new Application();
// skip to the form part ...
$app->match('/', function (Request $request) use ($app) {
// some default data for when the form is displayed the first time
$data = array(
'name' => 'Your name',
'email' => 'Your email',
);
$form = $app['form.factory']->createBuilder('form', $data)
->add('name')
->add('email')
->add('gender', 'choice', array(
'choices' => array(1 => 'male', 2 => 'female'),
'expanded' => true,
))
->getForm();
if ('POST' == $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$data = $form->getData();
// do something with the data
// redirect somewhere
return $app->redirect('completed');
}
}
// display the form
return $app['twig']->render('index.html', array('form' => $form->createView()));
});
Would i then create a page like so?
<?php // app.php
$app->match('complete') use function ($app) {
// sorry psuedocode
foreach ($REQUEST as $key=> $var) {
echo "$key: $var";
}
}
You could try using a forward. http://silex.sensiolabs.org/doc/usage.html#fowards
// where params is the values from your POST
$subRequest = Request::create('/otherpage', 'GET', $params);
return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);