I have a form with submit buttons save, save and close, save and view, and save and add, as usual in TYPO3. Each button is a <input type='image'> item, and the only difference is the name argument of the input. In my controller, how can I determine which submit button was clicked, in order to redirect to the right action?
You should not redirect to actions from the controller. It's better to call the correct action when a certain button is clicked. To keep the logic clear, you could use the f:link.action viewhelper for instance. Here is a good documentation about the viewhelpers: ViewHelper Reference. You can set an action and a controller attribute to this viewhelper. So no need to decide which button was clicked in the controller. To keep and pass your form data you should use the f:form ViewHelpers and write the form data onto an object.
The first problem I had was the name of the <input> that wasn't right. In order to get the right name, I have to build the tag using a ViewHelper derived from AbstractFormFieldViewHelper.
Now that the <input> tag is rendered the right way, I can see the name of the clicked <input> into $this->request->arguments.
For completeness, here is the code of the ViewHelper I used:
class IconSubmitViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper {
/**
* #var string
*/
protected $tagName = 'input';
/**
* Initialize the arguments.
*
* #return void
* #api
*/
public function initializeArguments() {
parent::initializeArguments();
$this->registerArgument('icon', 'string', 'Icon name', true, 'actions-document-close');
$this->registerTagAttribute('src', 'string', 'Image source', false, 'clear.gif');
$this->registerUniversalTagAttributes();
}
/**
* Renders an icon link as known from the TYPO3 backend
*
* #return string the rendered icon link
*/
public function render() {
$name = $this->getName();
$this->registerFieldNameForFormTokenGeneration($name);
$this->tag->addAttribute('type', 'image');
$this->tag->addAttribute('name', $name);
$this->tag->addAttribute('class', 'c-inputButton');
return \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon($this->arguments['icon'], array('title' => $this->arguments['title'], 'html' => $this->tag->render()));
}
}
And here is the code in the Controller that redirect to the right page:
private function submitRedirect($myobject) {
if ($this->request->hasArgument('_savedok')) {
$this->redirect('edit', NULL, NULL, array('myobject'=>$myobject));
}
if ($this->request->hasArgument('_savedokclose')) {
$this->redirect('list');
}
if ($this->request->hasArgument('_savedoknew')) {
$this->redirect('new');
}
}
Related
I'm using the activitybar viewContainer to add a sidebar icon specific to my extension. When you click the icon in the sidebar it opens a view that reveals a list. The list can be updated anytime. I would like the icon to have a number which shows how many items are in the list, exactly like the source control extension and the file explorer when files are unsaved.
It looks like this will be released in v1.72 (it is in the Insiders Build now - the demo is from the Insiders Build).
The api for badges on ViewContainers is quite simple:
export interface TreeView<T> extends Disposable {
// other stuff
/**
* The badge to display for this TreeView.
* To remove the badge, set to undefined.
*/
badge?: ViewBadge | undefined;
// other stuff
}
and here is what a ViewBadge is:
/**
* A badge presenting a value for a view
*/
export interface ViewBadge {
/**
* A label to present in tooltip for the badge.
*/
readonly tooltip: string;
/**
* The value to present in the badge.
*/
readonly value: number;
}
So this code works:
// in a class that has a TreeView named 'tabView'
public tabView: vscode.TreeView<treeNodes>;
this.tabView = vscode.window.createTreeView('editor-groups',
{ treeDataProvider: this.myTreeProvider,
showCollapseAll: true,
canSelectMany: true,
dragAndDropController: this.myTreeDragController
});
// value is a number, tooltip and value are NOT optional
this.tabView.badge = {tooltip:"my badge tooltip", value: vscode.window.tabGroups.all.length};
and then you can update this.tabView.badge with a new value whenever you want (it seems you have to keep including the tooltip each time you update the value though).
Here it is working on an extension I wrote:
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
I have added a second submit button to my form, now Symfony2 complains about it: "This form should not contain extra fields"
Although I added this option in the formtype:
public function getDefaultOptions(array $options)
{
return array(
'csrf_protection' => false,
);
}
Any ideas?
You can most certainly have multiple submit buttons. Make sure the button is not in the same array as the other form fields.
So, for example, if your form fields have a name FormType[field_name], you can't have FormType[submit_btn] as the name of the button and you must choose a different one.
Your controller can act differently depending on the button pressed. If your submit buttons are named submit_1 and submit_2 you can have something similar to
if($this->getRequest()->request->has('submit_1')) {
// do stuff
} else {
// do other stuff
}
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.
I assume it's a common requirement to have forms in your web apps that have
Edit Delete
buttons under them. But ZF puts one button under another, which is counter-intuitive.
I guess ViewScript decorator could help me completely override button html.
But how to do it across other forms, to avoid duplicating?
May be I am overcomplicating and I just should somehow paste html code instead of button element objects?
This is the code I use in my own Form class that all my forms inherit from. The main trick is to only use the ViewHelper Decorator on the button itself, and stick the buttons in a displaygroup that uses a DtDdWrapper and wraps the buttons in a <div class='buttons'> for extra styling options
protected $_buttons = array();
/**
* Sets a list of buttons - Buttons will be standard submits, or in the getJson() version
* they are removed from display - but stuck in the json in the .buttons property
*
* $buttons = array('save'=>'Save This Thing', 'cancel'=>'Cancel') as an example
*
* #param array $buttons
* #return void
* #author Corey Frang
*/
public function setButtons($buttons)
{
$this->_buttons = $buttons;
foreach ($buttons as $name => $label)
{
$this->addElement('submit', $name, array(
'label'=>$label,
'class'=>$name,
'decorators'=>array('ViewHelper'),
));
}
$this->addDisplayGroup(array_keys($this->_buttons),'buttons', array(
'decorators'=>array(
'FormElements',
array('HtmlTag', array('tag'=>'div', 'class'=>'buttons')),
'DtDdWrapper'
)
));
}
// Example from form::init()
$this->setButtons(array('save'=>'Save Entry', 'delete'=>'Delete Entry'));
Have a read through this tutorial on Zend Developer Zone:
Decorators-with-Zend_Form.
Button decorators can be modified in Form's constructor.
Buttons should be left without HtmlTag decorator to disable being on separate lines due to dt/dd tags, HtmlTag decorator can be remove like this:
$buttonobject->setDecorators(array(
'ViewHelper',
//array('HtmlTag', array('tag' => 'dd')),
//array('Label', array('tag' => 'dt')),
));
Comments are for demonstration purposes only.
Additionally, buttons may be grouped into a fieldset, for styling purposes:
$this->addDisplayGroup(array('delete','submit'),'buttons');
Optional site.css code:
#fieldset-buttons { border: none; }