Zend Forms email element changing to text - php

I'm trying to create an input of type email in Zend Forms but I cannot accomplish the desired result.
I've created a custom class:
namespace AAA\Forms\Elements;
class Email extends \Zend_Form_Element_Text
{
function __construct($name, $label, $required)
{
parent::__construct($name);
$this->setAttrib('type', 'email');
$this->setLabel($label)->setRequired($required);
}
}
And then I'm using it like this:
class Application_Form_Register extends Zend_Form
{
public function init()
{
// …
$email = new AAA\Forms\Elements\Email('email', 'E-mail:', true);
$this->addElement($email);
// …
}
}
And what I get is:
<input type="text" name="email" id="email" value="" type="email">
Note the two type parameters.
I have set HTML5 doctype ($documentType = new Zend_View_Helper_Doctype(); $documentType->doctype('HTML5'); in Bootstrap.php) and I have also tried this:
function __construct($name, $label, $required)
{
$options = array();
$options['type'] = 'email';
parent::__construct($name, $options);
// …
}
I've read Zend HTML5 Form element types but none of the answers work. I've tried also Glitch library but the result is the same.
Anyone knows how to force Zend Framework to use HTML5 form controls?

You will need to implement your own view helper for rendering the email form element as well.
Zend_Form_Element_Text uses the formText view helper (Zend/View/Helper/FormText.php) to render the HTML input and it is hard coded to output <input type="text" when rendering the element.
Two possible ways to handle this would be to:
Remove the ViewHelper decorator from the element and use the ViewScript helper to render the element.
Make your own view helper formEmail almost identical to formText except that it outputs type="email"; and set the public $helper property in your Element class to formEmail. You will have to register the path to the formEmail helper using Zend_View::addHelperPath() so it will be found by the ViewHelper decorator.

Related

how to "escape" the output zf1?

How "escape" the output of a string so js on the search line will not work? In Zend Framework1(v. 1.12.3).
<div id="search-box">
<input type="text" placeholder="<?php echo $this->languageText('TEXT_SEARCH_OUR_SITE',"Search Our Site"); ?>" name="query" id="query" />
<div class="search-box-bk"></div>
</div>
I tried this, but it didn't work
placeholder="<?php echo $this->escape($this->languageText('TEXT_SEARCH_OUR_SITE',"Search Our Site"));
Sadly Zend 1 does not have good escaping mechanism by default. ->escape() only uses standard PHP method htmlspecialchars.
You can set what escape method to use in Controller by getting View and using method setEscape('htmlentities') ( setEscape(array('Class/Object','method)))
(response for comment)
In one of my projects I've used Zend2 Escaper. First I've copied Escaper to my folder in Library (i renamed it to Adx_Escaper so it fits in existing library - I'm lazy ;)). Next I've created ViewHelper (resources.view.helperPath.Adx_View_Helper = "Adx/View/Helper/"(application.ini)) with content like this:
class Adx_View_Helper_Escaper extends Zend_View_Helper_Abstract
{
protected $escaper = null;
public function Escaper()
{
if ($this->escaper === null) {
$this->escaper = new Adx_Escaper();
}
return $this;
}
public function html($string)
{
return $this->escaper->escapeHtml($string);
}
/* ... */
Then i could just use $this->escaper()->html('SomeText') (now I see it would be even simpler to just return Escaper in constructor, but works eiter way).

Zend 2.0: 500 error when creating form element

I am learning Zend Framework (2.0), and I'm stuck at creating forms.
Here is the code I used (Inside a controller):
use Zend\Form\Element;
use Zend\Form\Form;
...
public function indexAction()
{
$element = new Element\Text('name');
//Nothing else
}
It always gives a 505 error, but if I comment out the line "$element ..." then it works (so the problem must be there).
Can someone point out what I have overlooked?
Also, as I see it, there are too many ways to create a form. For example, I have tried:
private function getSignupForm() {
//Create Form
$form = new Zend_Form();
$form->setAction('success');
$form->setMethod('post');
$form->setAttrib('sitename', 'mysite');
//Add Elements
//Create Username Field.
$form->addElement('text', 'username');
$usernameElement = $form->getElement('username');
$usernameElement->setLabel('Username:');
$usernameElement->setOrder(1)->setRequired(true);
return $form;
}
This way, it worked, but that is not the way the tutorial says link. So in which way should I should write it?
Thanks.

Render custom Form Elements using the FormElement ViewHelper in Zend Framework 2

I've created a new form element class for a special, complex purpose (text input field with an add-on button to open a "search wizard" popup).
To render this element properly, I've also created a form view helper. Everything works and is fine so far.
However, if I try to render the form using the FormCollection view helper, the element is rendered as a basic input element. That's because the FormElement view helper, which the FormCollection helper relies on, uses a hard-coded series of if clauses to map the element's type to a specific form view helper. It can't map my element's class and thus falls back to FormInput.
I.e. (taken from Zend/Form/View/Helper/FormElement.php, line 41-49):
if ($element instanceof Element\Button) {
$helper = $renderer->plugin('form_button');
return $helper($element);
}
if ($element instanceof Element\Captcha) {
$helper = $renderer->plugin('form_captcha');
return $helper($element);
}
...
$helper = $renderer->plugin('form_input');
return $helper($element);
and so on.
I've got a little stuck here because this architecture doesn't really promote extensibility.
The only solution that came to my mind (except rendering the form by hand) is to extend the FormElement view helper class and thus create my own CustomFormElement view helper. However, because of its complexity, I've put the custom element into an own module. So I'd have to write this CustomFormElement helper dynamically to add custom elements from any module. I don't think this is a recommended procedure.
Is there another solution or is maybe even my complete approach unrecommended? Thanks in advance!
I think the simplest way is to extend Zend\Form\View\Helper\FormElement, handle your field types in your render() method and register your FormElement as default FormElement for your application/module. Assuming that you have your custom TestField that you would like to render:
namespace Application\Form\View\Helper;
use \Zend\Form\ElementInterface;
use \Zend\Form\View\Helper\FormElement
use \Application\Form\Element\TestField;
class MyFormElement extends FormElement
{
public function render(ElementInterface $element)
{
$renderer = $this->getView();
if (!method_exists($renderer, 'plugin')) {
// Bail early if renderer is not pluggable
return '';
}
//your custom fields go here...
if ($element instanceof TestField) {
$helper = $renderer->plugin('\Application\Form\View\Helper\FormTestField');
return $helper($element);
}
return parent::render($element);
}
}
And in Application/config/module.config.php:
'view_helpers' => array(
'invokables' => array(
'form_element' => 'Application\Form\View\Helper\MyFormElement',
)
)
Get your hands on the FormElement view helper any way you can and addType to overwrite the view helper used. i.e. in view, just before you render your form:
<?php $this->plugin('FormElement')->addType('text', 'formcustom'); ?>
This will overwrite the view helper used in the FormRow,FormCollection helpers using your view helper by the key name:
in your config
'view_helpers' => array(
'invokables' => array(
'formcustom' => 'Application\Form\View\Helper\FormCustom',
)
),
When this question was asked the method may not have been there. But it is now.
The following is what I've done and feels like the right level of keeping things separate and neat.
Given:
A new element: MyModule\Form\MyElement which extends Zend\Form\Element
A new view helper class for MyElement: MyModule\Form\View\Helper\FormMyElement which extends Zend\Form\View\Helper\AbstractHelper
Here's how you register your view helper to be used to render your element by adding the following to module.config.php:
'view_helpers' => array(
'invokables'=> array(
'formMyElement' => 'MyModule\Form\View\Helper\FormMyElement',
),
'factories' => array(
'formElement' => function($sm) {
$helper = new \Zend\Form\View\Helper\FormElement();
$helper->addClass('MyModule\Form\MyElement', 'formMyElement');
return $helper;
}
),
),
The key is that you are providing a new factory method for FormElement that still creates the same, standard class (no need to override it), but also calls the addClass method to register your custom helper as the proper helper for your custom element. If you don't want to make the short-name for your helper, you can drop the invokables section and put the FQCN in the addClass call, but I like having the short name available.
This is the best method I've found so far. Ideally, you wouldn't have to take over the construction of the FormElement and could just modify a config that gets passed to it. The downside of this approach is that if you have multiple modules that define custom form elements they are going to clash if they all try to re-define the FormElement factory. You can't specify additions in multiple modules this way. So, if someone finds a better config that can be set that simply gets passed to the FormElement::addClass() method, please let me know.
BTW, I found this page which doesn't address the view helper side of the equation, but talks about registering new form element classes and how to over-ride the built in classes: http://framework.zend.com/manual/current/en/modules/zend.form.advanced-use-of-forms.html
----custom form element-----
namespace App\Form\View\Helper;
use Zend\Form\View\Helper\FormElement as ZendFormElement;
/**
* Description of FormElement
*/
class FormElement
extends ZendFormElement
{
public function addTypes(array $types)
{
foreach ($types as $type => $plugin) {
$this->addType($type, $plugin);
}
}
}
---- application module.config.php--------------
//..........
'view_helpers' => array(
'invokables' => array(
'formRTE' => 'App\Form\View\Helper\FormRTE',
),
'factories' => array(
'formElement' => function($sm) {
$helper = new App\Form\View\Helper\FormElement();
$helper->addTypes(array(
'rte' => 'formRTE',
));
return $helper;
}
),
),
//.........
Seems like we're both running into Form issues with Zend. I think that it could be better integrated with the whole MVC structure.
I think that your approach is sound. What I might think of doing is the following
Give your elements a variable named helper like in ZF1.
Create the custom form element renderer that will ALSO check the renderer attribute of a form element to decide on how to render it.
You could re-use the ViewHelperProviderInterface or create your own interface:
class CustomElement implements ViewHelperProviderInterface
{
public function getViewHelperConfig()
{
return array('type' => '\My\View\Helper');
}
}
or
class CustomElement implements FormHelperProviderInterface
{
public function getFormHelperConfig()
{
return '\My\View\Helper';
// or
return new My\View\Helper();
}
}
Then in your FormElement class you can do the following:
if ('week' == $type) {
$helper = $renderer->plugin('form_week');
return $helper($element);
}
if ($element instanceof THEINTERFACE) {
return $renderer->plugin($element->getFormHelperConfig());
}
$helper = $renderer->plugin('form_input');
return $helper($element);
This is probably what you had in mind anyway.
You'd probably be better off creating your own interface since the first one already has some sort of meaning behind it and it might confuse someone.
Aside from that, each module would then ONLY have to provide a helper_map key in the module configuration to have it's view helpers available during rendering with the MVC components.

Zend Form: how to automatically set the class of an element to required if required option is set to true?

Is this possible? I'm trying to use jorn's jQuery Validation plugin, and I would like to avoid having to add 'class' => 'required' if i'm already setting the required => true option. Thx in advance for any input!
Not possible using standard ZF classes. You can accomplish this by creating a custom decorator to replace the standard ViewHelper.
class My_Form_Decorator_ViewHelper extends Zend_Form_Decorator_ViewHelper
{
public function render($content)
{
$element = $this->getElement();
if ($element->isRequired()) {
$class = $element->getAttrib('class'); // append to current attrib
$element->setAttrib('class', $class . ' required');
}
return parent::render($content);
}
}
Of course, you also might want to add the prefix path to this decorator in your form.

Different form formatter for embeded form?

I'm trying to change the form formatter of the embeded form. Is it possible to approach something like this?
class sfOuterForm extends sfForm {
public function configure()
{
$innerForm = new sfForm();
$this->embedForm('inner', $innerForm);
$this->getWidgetSchema()->setFormFormatter('list');
$this->getEmbeddedForm('inner')->getWidgetSchema()->setFormFormatterName('table');
}
}
i'm expecting the following:
echo (new sfOuterForm())
outputs:
<li><label>Outer Label</label><input type="text" /></li>
<li>
<table>
<tr><td><label>Inner Label</label></td><td><input type="text" /></td></tr>
</table>
</li>
Once a form is embedded, it's original widget schema and validator schema do nothing - they've been merged into the top level schemas. Thus, you need to set the form formatter before embedding:
$this->getWidgetSchema()->setFormFormatter('list');
$innerForm = new sfForm();
$innerForm->getWidgetSchema()->setFormFormatterName('table');
$this->embedForm('inner', $innerForm);
It's worth a look into sfForm::embedForm to see what's going on internally.
I'll answer my question by myself :)
The problem arised when i tried to change formatter for relation's embedded forms. I solved this as follows:
class sfOuterForm extends sfForm {
public function configure()
{
$innerForm = new sfForm();
$this->embedRelation('relationName');
$this->getWidgetSchema()->setFormFormatter('list');
$this->getEmbeddedForm('relationName')->getWidgetSchema()->setDefaultFormFormatterName('table');
}
}
Hope this will help someone :)

Categories