I want to make forms
which has three scenes
1.input view (which has 'confirm' button)
2.draft check view (which has 'send' button)
3.send view
in method 1 you can input the data then click 'confirm' button
the system write the data in DB as draft.
in method 2 you see the data and confirm then push 'send' button
the system write the flg 'confirmed'
these are my code.
it works well method 1 but if I push 'send' button in method2.
it doesn't go.
if ($form->isValid()) {
My idea is something wrong??
public function writeEvalStudentAction(Request $request,$keyStr){
...
$form = $this->createFormBuilder($evalStudent)
->add('commentToStudent')
->add('confirm','submit')->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
if ($form->has('send')){
if ($form->get('send')->isClicked()){
//set confirm flg then shows thanks screen.
$evalStudent->setConfirmed(true);
$em->persist($evalStudent);
$em->flush();
return $this->render('AcmeMemberBundle:Default:confirmedEvalStudent.html.twig');
}
}
if ($form->has('confirm')){
if ($form->get('confirm')->isClicked()){
// write in the db as draft.
$evalStudent->setCommentToStudent($form->get('commentToStudent')->getData());
$em->persist($evalStudent);
$em->flush();
$form = $this->createFormBuilder($evalStudent)->add('send','submit')->getForm();
return $this->render('AcmeMemberBundle:Default:checkEvalStudent.html.twig',
array('form' => $form->createView()));
}
}
return $this->render('AcmeMemberBundle:Default:writeEvalStudent.html.twig',
array('form' => $form->createView()));
}
Split it up in 4 controller actions with 4 separate routes. Whereas route2 and route3 require the id of your draft object in the routing parameters.
Make the form1 from step 1 point to step2.
In step2 validate the form and if it is ok insert to db and get your id, then show form2 which points to step 3, if not show form1 with form errors.
Same for step2->step3 and step3->step4.
In step 4 you convert your draft to a final object and persist it and remove the draft.
Related
Since 3 weeks i try to learn php with the symfony framework.
I want to build an application with which i can track my expanses.
I made good progress but since 2 days i have a little logic problem so maybe someone can help me here.
I want to make a dashboard.(the main side of the project) There the user can monitor the expenditures.
This works. Now i want also a form at the dashboard, so the user can add new expenditures. I already implement a form but with a extra route. So in my ExpenditureController i have the functions dashboard and the function addExpenditure which generate different twig.html templates.
So the user can monitor his expenditures with ...budgetapp/expenditure/dashboard
and he can add new Expenditure with ...budgetapp/expenditure/addexpenditure
My Dashboard-Function
#[Route('/dashboard/', name: 'dashboard')]
public function dashboard(ExpenditureRepository $ar)
{
$user = $this->getUser();
$expenditures = $ar-> findexpendituresOfUser($user);
return $this->render('expenditure/dashboard.html.twig', [
'expenditures' => $expenditures,
]);
}
The expenditure/dashboard.html.twig shows the Expentiures of the current user in a table
My addExpenditure-Function
public function addExpenditure (ManagerRegistry $doctrine, Request $request){
$em = $doctrine->getManager();
$expenditure = new Expenditure();
$form = $this->createForm(ExpenditureType::class, $Expenditure);
$form->handleRequest($request);
if($form->isSubmitted()){
$em->persist($expenditure);
$em->flush();
}
return $this->render('expenditure/addexpenditure.html.twig', [
'addexpenditureForm' => $form->createView()
]);
}
The expenditure/addexpenditure.html.twig looks like this:
{% block body %}
<div class="container">
{{form(eintragenForm)}}
</div>
{% endblock %}
My problem /mistake in thinking:
How can i implement the form to the dashboard? So of course i can take the code from the addexpenditure function and put it 1:1 in the dashboard-funciton. but i dont think this is the right way? I also tried to including template fragments with the offical Embedding Controllers Documentation of Symfony, but this also dont work.
So someone can help me with a suggestion how you would handle this in your project?
Best regards
Markus
There are two possible solutions: put both view and add logic inside one controller's action, or separate them. Since you probably have some validation, it's reasonable to have both add and view code inside one action (otherwise, you'll have to pass errors via sessions, which is not very pretty). So basically, your dashboard/add action will look like this:
#[Route('/dashboard/', name: 'dashboard')]
public function dashboard(Request $request, ExpenditureRepository $ar, ManagerRegistry $doctrine)
{
$expenditure = new Expenditure();
$form = $this->createForm(ExpenditureType::class, $expenditure);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $doctrine->getManager();
$em->persist($expenditure);
$em->flush();
return $this->redirectToRoute('dashboard');
}
}
$user = $this->getUser();
$expenditures = $ar-> findexpendituresOfUser($user);
return $this->render(
'expenditure/dashboard.html.twig',
[
'expenditures' => $expenditures,
'addexpenditureForm' => $form->createView(),
]
);
}
What's happening here:
First you check if POST http method was used, if it was - it means
that form has been submitted and you can handle it. There is an alternative solution without checking request method, see comments for more.
If this is a GET request, just show ordinary dashboard
If the form is submitted and it's valid - save data and redirect to
the same page. Otherwise, you'll need to empty all submitted data
from the form, etc. (it's not the right way to do it)
If the form is invalid, do not redirect, just render the page
normally, and all errors will be shown.
Finally, you of course have to render the form on your dashboard.html.twig like you did: {{form(eintragenForm)}}
I have an entity (about 20/25 fields) and i want to edit it with a form.
I just want to edit (and display) few form field.
The problem is, all fields displayed are correctly update, but fields that are not rendered are update with "null" value by default.
My controller :
$em = $this->getDoctrine()->getManager();
$LaboRequest= $em->getRepository('MyBundle:LaboRequest')->find($id);
$form = $this->createForm('MyBundle\Form\LaboRequestType', $LaboRequest);
if ($request->isMethod('POST') && $form->handleRequest($request)->isSubmitted() && $form->isValid()) {
$em->persist($LaboRequest);
$em->flush();
return $this->redirectToRoute(...);
}
return $this->render('...', array(
'LaboRequest' => $LaboRequest,
'form' => $form->createView(),
));
I only render few fields in my view, so i can understand, by default symfony use "null" for fields that are not render.
But is there a way to edit a part of an entity and not affect data of the entity with "null" value ?
I'm not sure you can do that.
But you can extend your original form and call
$builder->remove('xxx')
for each field you want to remove
Using Symfony, version 2.3 and more recent, I want the user to click on a link to go to the edition page of an already existing entity and that the form which is displayed to be already validated, with each error associated to its corresponding field, i.e. I want
the form to be validated before the form is submitted.
I followed this entry of the cookbook :
$form = $this->container->get('form.factory')->create(new MyEntityFormType, $myEntity, array('validation_groups' => 'my_validation_group'));
$form->submit($request->request->get($form->getName()));
if ($form->isValid()) {
...
}
But the form is not populated with the entity datas : all fields are empty. I tried to replace $request->request->get($form->getName()) with $myEntity, but it triggered an exception :
$myEntity cannot be used as an array in Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
Does anyone know a method to feed the submit method with properly formatted datas so I can achieve my goal ? Note : I don't want Javascript to be involved.
In place of:
$form->submit($request->request->get($form->getName()));
Try:
$form->submit(array(), false);
You need to bind the the request to the form in order to fill the form with the submitted values, by using: $form->bind($request);
Here is a detailed explanation of what your code should look like:
//Create the form (you can directly use the method createForm() in your controller, it's a shortcut to $this->get('form.factory')->create() )
$form = $this->createForm(new MyEntityFormType, $myEntity, array('validation_groups' => 'my_validation_group'));
// Perform validation if post has been submitted (i.e. detection of HTTP POST method)
if($request->isMethod('POST')){
// Bind the request to the form
$form->bind($request);
// Check if form is valid
if($form->isValid()){
// ... do your magic ...
}
}
// Generate your page with the form inside
return $this->render('YourBundle:yourview.html.twig', array('form' => $form->createView() ) );
I am not able to redirect a custom form to specific action.
What I am trying is
<?= Html::submitButton( 'delete-selected' ,['class' => 'btn btn-primary']) ?>
here delete-selected is my custom action in controller appointment.
I have also tried like this:
public function actionDeleteForm()
{
return $this->render('delete');
return $this->redirect(['delete-selected']);
}
public function actionDeleteSelected()
{
Appointment::deleteAll(['doctor_name' =>4]);
return $this->redirect(['index']);
}
What I am trying to do is actually delete some records using the form. The form name is delete having a select drop-down field.
I want to post the data to action deleteselected and use the $_POST variable in the delete query.
How can I do this?
Thanks.
Any submit button that you put on your form will submit to the url specified in the action parameter of the form. If you haven't specified one, then Yii will use the current controller/action of the form. If you want to override this behavior, then you will need to specify an action for the form. e.g.
$form = ActiveForm::begin([
'action' => 'appointment/delete-selected'
]);
in actionDeleteForm you have
return $this->render('delete');
before
return $this->redirect(['delete-selected'])
this second instruction will never be executed because you have already made a return to the function and then control has already been returned to the caller
This is somewhat a note for Joe Miller's answer. If you are supposed to override the form's action with an action of a controller, make sure you make the value of 'action' as an array:
$form = ActiveForm::begin([
'action' => ['appointment/delete-selected']
]);
It will treat the action as a route to action delete-selected in controller appointment.
From this page:
main_dev.php/player/new
to (when I click submit):
main_dev.php/player/edit/player_id/(no id)
if I put an id here it displays fine.
When I click the submit button (somehow it saves) but displays this:
404 | Not Found | sfError404Exception
Object Player does not exist().
this is my baseform:
$this->setWidgets(array(
'player_id' => new sfWidgetFormInputHidden(), //primary key auto increment()
'player_name' => new sfWidgetFormInputText(),
'player_gold' => new sfWidgetFormInputText(),
'chara_id' => new sfWidgetFormInputText(),
'open_social_id' => new sfWidgetFormInputText(),
));
im suspecting that the issue here is that player_id is not displayed and is auto increment. that means that when i submit the form player_id is left blank and since symfony cannot find where to get the id for the reference to display a record it goes 404, is there any workaround in this?
and my action.class is left from the default(instance when i generated it) so i think is not an issue
heres what the code for saving the form:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid())
{
$Player = $form->save();
$this->redirect('player/edit?player_id='.$Player->getPlayerId());
}
}
and ofcourse for the new page controller:
public function executeNew(sfWebRequest $request)
{
$this->form = new PlayerForm();
}
If the POST request saves a new Player object (in the database), it is not your BasePlayerForm.class, nor the submit url.
If your routing works when manually entered, and not when called within the action class, then your routing.yml is probably not the problem.
If you have not over-written the configure() of the BasePlayerForm.class.php (in PlayerForm.class.php, or anywhere else), then it is not in your lib/form/ classes.
Either this answer is useless (sorry) or you do not actually mean that the action "saves" the object to the database - in which case, check the submit url/request from the newSuccess template; also verify your routing:
Your newSuccess.php form tag action should POST to main_dev.php/player:
<form method="post" action="/main_dev.php/player">
[And pass the id rendered in html as <input type="hidden" name="player[player_id]" id="player_id" />.]
Lastly, the edit routing in the url will normally match player/:player_id/edit - check if you actually have an auto-created "id" column in your schema/database in addition to the "player_id" which might really be what is causing this.