Where to put controller code for Yii2 sidebar modal form? - forms

I want to have a modal Report Issue form in the sidebar that loads on every page. I can't seem to wrap my head around where to place the controller/form initialization code.
A typical controller action:
public function actionContact()
{
$model = new Feedback();
if ($model->load(Yii::$app->request->post()) && $model->sendEmail()) {
Yii::$app->getSession()->addFlash('success', 'Thank you for contacting us.<br /><br />We will respond as soon as possible.');
$model = new Feedback();
}
if (Yii::$app->request->isPjax) {
return $this->renderAjax('contact', [
'model' => $model,
]);
} else {
return $this->render('contact', [
'model' => $model,
]);
}
}
The $model is set when the action is first called, but if the modal is to be placed in the sidebar, every controller and/or controller/action could be called, and I don't want to have the $model initialization repeated each time (DRY).
I'm not sure if this is a prime condition for a custom widget, or a controller->beforeAction, or something else altogether.
Any insight is greatly appreciated.

Use a widget. The widget will create an empty $model and pass it to it's view. You can insert the widget in any view or in the layout too.
Regarding the
every controller and/or controller/action could be called
why would any controller be called? Your form should send the info to 1 controller/action not any of them. The widget will be shown by any controller/action but the widget's form will always just call 1.

Related

Symfony 2 Forms - add new item to Collection server-side, depending on button clicked

I have a form which contains a Collection of an unspecified number of subforms. I want to have functionality allowing the user to add a new, blank item to the Collection for them to fill in. The Symfony docs tell us how to do this using Javascript clientside to add new blank form controls, which are then submitted and persisted as normal, but I'd like to do it serverside in the controller, without Javascript.
The problem I'm encountering is to do with the way Symfony Forms work. I have an "Add" button added to my main form, and I intend to detect whether it is that button which has been clicked, so that I can add the blank item to the Collection and re-render the form. But to detect the click I need to call $this->createForm and at that point the form is fixed with the original set of items, it's too late to add an extra one.
//Symfony Action
//A Person has many Selections
$person = $this->getPerson($id)
//All fields are frozen at this point, according to data in $person!
$form = $this->createForm(new SelectionsType($lookups), $person);
$form->handleRequest($request);
//Ideally I'd somehow do this test earlier, but I need $form to do it...
if ($form->get('add')->isClicked() )
{
//TOO LATE!
$person->getSelections()->add(new Selection() );
}
if ($form->isValid())
{
if ($form->get('save')->isClicked() )
{
//Persist
}
}
//Render page etc
Things I've thought about:
Putting the Add button in a completely different form on the same page, which submits to a different Action which can then do some preparatory work before forwarding to the main Action above
Inspecting submitted HTTP data directly to note that Add has been clicked (shame not to use the standard Symfony method)
Give up and use Javascript as suggested (it might work in this example, but I'd like to have the option of carrying out server-side activity (without AJAX...) as part of adding the new blank item)
How can I best achieve this in a proper Symfony way?
EDIT Just seen this: https://github.com/symfony/symfony/issues/5231, which is essentially a feature request to allow what I'm after. One suggestion a commenter makes is to add a blank item to the Collection and then remove it if it's not needed - I don't know how one would do that, but it sounds promising.
ANOTHER EDIT It occurs to me that, because I need two different aspects of the $form I'm creating, I could maybe just make the $form, use it to handle the request, detect the button click, and then throw that $form away, before altering my model and creating another $form. I don't know if that would somehow fall foul of some rules about handling the submission twice.
I'm not 100% but I think you could do the following...
//Symfony Action with (Request $request, ...)
//A Person has many Selections
$person = $this->getPerson($id)
//All fields are frozen at this point, according to data in $person!
$form = $this->createForm(new SelectionsType($lookups), $person);
if ($request->isMethod('POST')) {
$form->submit($request);
if ($form->get('add')->isClicked()) {
// Add thing
} elseif ($form->isValid()) {
// or
// } elseif ($form->get('save')->isClicked() && $form->isValid()) {
// Persist and what not
}
}
//Render page etc
I haven't tested it so I don't know whether it will trigger the form errors (or if it will actually work) so if it does (or it doesn't) I apologise.
What I did in the end was have my Add button hit a separate Action, which then delegates to the main action with a flag to say "add a new Selection", as below:
public function selectionsAddAction(Request $request, $id)
{
return $this->selectionsAction($request, $id, true);
}
public function selectionsAction(Request $request, $id, $addNew = false)
{
$person = $this->getPerson($id);
//Also use "add mode" if we just deleted the last one!
if (!$person->getSelections()->count())
{
$addNew = true;
}
//$addNew is set by a separate action, hit by a different form with the Add button in
if ($addNew)
{
$person->getSelections()->add(new Selection() );
}
//We now have the right number of items, and can build the form!
$form = $this->createForm(new SelectionsType($lookups), $person);
//...
}

adding Zend_Form_Element_Captcha to form causes form to not display

I am having trouble getting a captcha element to display in a signup form. It was working previously, but now for some reason when I try to add the captcha element to the form the entire form does not display.
Below is the function in my controller file to create the form
private function getSignupForm()
{
// create form
$form = new Zend_Form();
$form->setAction('success');
$form->setMethod('post');
$form->setAttrib('sitename', 'loudbite');
// add elements
require "form/elements.php";
$loudbiteElements = new Elements();
// create username field
$form->addElement($loudbiteElements->getUsernameTextField());
// create email field
$form->addElement($loudbiteElements->getEmailTextField());
// create password field
$form->addElement($loudbiteElements->getPasswordTextField());
// add captcha
$form->addElement($loudbiteElements->getCaptcha());
// create submit button
$form->addElement('submit', 'submit');
$submitElement = $form->getElement('submit');
$submitElement->setLabel('Create My Account!');
return $form;
}
and here is the action to pass the form to the corresponding view
public function newAction()
{
// get the form
$form = $this->getSignupForm();
// add the form to the view
$this->view->form = $form;
}
If I comment out the line in my getSignupForm() function where I add the captcha to the form then the form will display ok minus the captcha element. This leads me to assume that there is a problem with the captcha contruction.
Below is the function in an external model file where the captcha is constructed
public function getCaptcha()
{
$captchaElement = new Zend_Form_Element_Captcha(
'signup',
array('captcha' => array(
'captcha' => 'Figlet',
'wordLen' => 6,
'timeout' => 600))
);
$captchaElement->setLabel('Please type in the words below to continue:');
return $captchaElement;
}
All the other form elements are created in this external model file. Based on the fact that the other elements display correctly if I do not add the captcha element, I assume it is not a problem with accessing the model file.
The last time I used this signup form everything was working ok! And I don't remember having changed anything between then and now.
Any help is greatly appreciated.
Regards
Roan

zend form elements display hidden field value

$emailmessage = new Zend_Form_Element_Hidden('emailmessage');
the hidden filed value, i.e 'emailmessage' retrieves the value of the same field name inside the database. However on loading the page, value of the 'emailmessage' cannot be seen, since the element is hidden.
Is there any way to display it without using any other form elements. I want it without using text, textarea, etc.
in controller you need to assign it to view and in the view you can echo it where ever you want:
controller
$form = new Your_Form();
$this->view->emailmessage = $emailmessage;
View
echo $this->escape($this->emailmessage);
You need to set formNote decorator for the element.
You do it by extending Hidden element or by setting decorator in the form.
Form
public function init()
{
// ...
$emailMessage = new Zend_Form_Element_Hidden();
$emailMessage->setDecorators(
array(
array('ViewHelper', array('helper' => 'formNote'))
)
);
$this->addElement($emailMessage, 'emailMessage');
// ...
}

Zend Framework Action Helper Problem

I'm a relative noob when it comes to Zend Framework, however I've got a form that I need to use if a couple of views so I thought I might use a Action Helper to instantiate the form set a few attributes and pass it to the relevant view. I've created the Action Helper and can call it from within the relevant controller's action, however when I try to pass the form to the action's view nothing gets rendered, ie:
$form = new Application_Form_Colour;
if($this->_request->isPost() && $form->isValid($this->_request->getPost()))
{
$model = new Application_Model_Colour();
$model->changeColour($form->getValues());
$form->reset();
}
else
{
$form->newColour->setAttrib('disabled', 'disabled');
}
$this->view->form = $form;
Is there something I am doing wrong or have I got the wrong idea of what an Action Helper can be used for? Maybe its not an Action helper that I need to use?
It turned out I was just being stupid! Instead of
$this->view->form = $form;
at the end of the Action Helper I should have done:
return $form;
Then in my controller:
$this->view->form = $this->_helper->myActionHelper->myActionHelperMethod();
Silly me...

set/add view from controller action

I'm trying to set a view script to be executed in addition to the currently requested action view script. I want to do this from the controller action itself in a way that this new view script output will be available from the layout $this->layout()->content helper.
I found the setView() method but don't know how to use it from the controller.
Thanks a lot.
If you just want to render some other view script from a controller just:
$this->render('someotherview');
Wich will render someotherview.phtml.
from: http://framework.zend.com/manual/en/zend.controller.action.html#zend.controller.action.viewintegration.render
class MyController extends Zend_Controller_Action{
public function fooAction()
{
// Renders my/foo.phtml
$this->render();
// Renders my/bar.phtml
$this->render('bar');
// Renders baz.phtml
$this->render('baz', null, true);
// Renders my/login.phtml to the 'form' segment of the
// response object
$this->render('login', 'form');
// Renders site.phtml to the 'page' segment of the response
// object; does not use the 'my/' subirectory
$this->render('site', 'page', true);
}
public function bazBatAction()
{
// Renders my/baz-bat.phtml
$this->render();
}
}
Should get you on the right track!
Also
$this->renderScript('path/to/index.phtml');
Works really well.