InputFilter "setRequired" not working for html5 multiple - forms

I'm having hard time with a weird behaviour of fileinput.
This is my form:
namespace Frontend\Form;
use NW\Form\Form;
use Zend\InputFilter;
use Zend\Form\Element;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
class EnrollStructure extends Form implements ServiceManagerAwareInterface
{
protected $sm;
public function __construct($name=null) {
parent::__construct("frmEnrollStructure");
$this->setAttribute("action", "/registrazione_struttura/submit")
->setAttribute('method', 'post')
->setAttribute("id", "iscrizione_struttura")
->setAttribute("class", "form fullpage");
$this->addInputFilter();
}
public function init()
{
$structureFs = $this->sm->get('Structure\Form\Fieldsets\Structure');
$structureFs->setUseAsBaseFieldset(true);
$structureFs->remove("id")
->remove("creationTime")
->remove("latLon");
$file = new Element\File("images");
$file->setAttribute('multiple', true);
$this->add($structureFs)->add($file);
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Iscriviti',
'id' => 'sbmtEnrollStructure',
'class' => 'submit_btn'
),
));
$this->setValidationGroup(
array(
'structure' =>
array(
'companyname',
'vatNumber',
'addressStreet',
'addressZip',
'addressCity',
'addressRegion',
'fax',
'publicPhone',
'publicEmail',
'website',
'status',
'ownerNotes',
'category',
'subcategory',
"facilities",
"agreeOnPolicy",
"agreeOnPrivacy",
"subscribeNewsletter",
"contact" => array("name", "surname", "email", "role", "phone"),
),
"images"
));
}
/**
* Set service manager
*
* #param ServiceManager $serviceManager
*/
public function setServiceManager(ServiceManager $serviceManager)
{
$this->sm = $serviceManager;
}
public function addInputFilter()
{
$inputFilter = new InputFilter\InputFilter();
// File Input
$fileInput = new InputFilter\FileInput('images');
$fileInput->setRequired(true);
$fileInput->getValidatorChain()
->attachByName('filesize', array('max' => "2MB"))
->attachByName('filemimetype', array('mimeType' => 'image/png,image/x-png,image/jpg,image/jpeg'))
->attachByName('fileimagesize', array('maxWidth' => 2048, 'maxHeight' => 2048));
$inputFilter->add($fileInput);
$this->setInputFilter($inputFilter);
}
}
Basically, I mainly use a fieldset which contains most of the data I request to the user, plus a File input field.
This is the Fieldset Structure: (most important parts..)
use Zend\Form\Element;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Validator\Identical;
use Zend\Validator\NotEmpty;
use Zend\Validator\Regex;
use Zend\Validator\StringLength;
class Structure extends Fieldset implements InputFilterProviderInterface, ServiceManagerAwareInterface
{
protected $sm;
public function __construct()
{
parent::__construct('structure');
}
public function init()
{
$this->setHydrator(new DoctrineHydrator($this->_entityManager(),'Structure\Entity\Structure'));
$this->setObject($this->sm->getServiceLocator()->get("Structure_Structure"));
$id = new Element\Hidden("id");
$name = new Element\Text("companyname");
$name->setLabel("Ragione Sociale");
...........
}
public function getInputFilterSpecification()
{
return array
(
"id" => array(
"required" => false,
),
"companyname" => array(
"required" => true,
"validators" => array(
array('name' => "NotEmpty", 'options' => array("messages" => array( NotEmpty::IS_EMPTY => "Inserire la ragione sociale")))
),
),
.....
}
}
This is my controller:
public function submitAction()
{
try {
$this->layout("layout/json");
$form = $this->getForm('Frontend\Form\EnrollStructure');
//$form->addInputFilter();
$structure = $this->getServiceLocator()->get("Structure_Structure");
$viewModel = new ViewModel();
$request = $this->getRequest();
if ($request->isPost())
{
$post = array_merge_recursive
(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($post);
if ($form->isValid())
{
$structure = $form->getObject();
$contact = $structure->getContact();
$this->getServiceLocator()->get('Structure_ContactService')->save($contact);
$files = $request->getFiles()->toArray();
if(isset($files['images']))
{
$count = 3;
foreach($files['images'] as $pos => $file)
{
$fpath = $this->getServiceLocator()->get('RdnUpload\Container')->upload($file);
if(!empty($fpath))
{
if(--$count ==0) break;
$asset = $this->getServiceLocator()->get("Application_AssetService")->fromDisk($fpath, $file['name']);
$this->getServiceLocator()->get("Application_AssetService")->save($asset);
$structure->addImage($asset);
}
}
}
$this->getServiceLocator()->get('Structure_StructureService')->save($structure);
$retCode = RetCode::success(array("iscrizione_struttura!" => array("form_submit_successfull")), true);
}
else
{
$messages = $form->getMessages();
if(empty($messages))
$retCode = RetCode::error(array("iscrizione_struttura" => array("need_at_least_one_file" => "missing file")), true);
else
$retCode = RetCode::error(array("iscrizione_struttura" => $messages), true);
}
$viewModel->setVariable("retcode", $retCode);
return $viewModel;
}
} catch(Exception $e)
{
throw $e;
}
}
The strange thing is that if i remove from the field "images" the "multiple" attribute everything works fine, causing the form not to validate and i get this message:
[images] => Array
(
[fileUploadFileErrorFileNotFound] => File was not found
)
While, if i set the attribute multiple, and the user does not upload a file i get no error, but the form gets invalidated (this is the reason for this "bad" code in my controller:)
$messages = $form->getMessages();
if(empty($messages))
$retCode = RetCode::error(array("iscrizione_struttura" => array("need_at_least_one_file" => "missing file")), true);
else
$retCode = RetCode::error(array("iscrizione_struttura" => $messages), true);

I found the problem was caused by the Jquery form plugin, without it it works fine. :( In case somebody needs, I think the correct action code can be found here (I haven't tryied it anyway)
https://github.com/cgmartin/ZF2FileUploadExamples/blob/master/src/ZF2FileUploadExamples/Controller/ProgressExamples.php

Related

Prestashop 1.7 renderform by admincontroller error

for my module i need to generate a form with helper. I found nothing with my error on the web so... I post again something...
Here my AdminYoutubeHomeController
<?php
class AdminYoutubeHomeController extends ModuleAdminController
{
public function __construct()
{
$this->bootstrap = true;
$this->display = 'view';
parent::__construct();
$this->meta_title = $this->l('Youtube');
if (!$this->module->active) {
Tools::redirectAdmin($this->context->link->getAdminLink('AdminHome'));
}
}
public function renderView()
{
/**
* If values have been submitted in the form, process.
*/
if (((bool)Tools::isSubmit('submitYoutubeHomeModule')) == true) {
$this->postProcess();
}
$this->context->smarty->assign([
'youtube_dir', _PS_MODULE_DIR_.'youtubehome',
'youtube_embeded' => "https://www.youtube.com/embed/",
'youtubeLink' => Configuration::get('YOUTUBEHOME_LINK_VIDEO')
]);
return $this->context->smarty->fetch(_PS_MODULE_DIR_.'youtubehome/views/templates/admin/youtubehome.tpl').$this->renderForm();
}
/**
* Create the form that will be displayed in the configuration of your module.
*/
public function renderForm()
{
$helper = new HelperForm();
$helper->show_toolbar = false;
$helper->table = $this->table;
$helper->module = $this;
$helper->name_controller = $this->module->name;
$helper->default_form_language = $this->context->language->id;
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0);
$helper->identifier = $this->identifier;
$helper->submit_action = 'submitYoutubeHomeModule';
$helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false)
.'&configure='.$this->module->name.'&tab_module='.$this->module->tab.'&module_name='.$this->module->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->tpl_vars = array(
'fields_value' => $this->getConfigFormValues(), /* Add values for your inputs */
'languages' => $this->context->controller->getLanguages(),
'id_language' => $this->context->language->id,
);
return $helper->generateForm(array($this->getConfigForm()));
}
/**
* Create the structure of your form.
*/
public function getConfigForm()
{
return array(
'form' => array(
'legend' => array(
'title' => $this->l('Settings'),
'icon' => 'icon-cogs',
),
'input' => array(
array(
'col' => 3,
'type' => 'text',
'prefix' => '<i class="icon icon-youtube-play"></i>',
'desc' => $this->l('Enter your youtube end link'),
'name' => 'YOUTUBEHOME_LINK_VIDEO',
'label' => $this->l('Link'),
),
),
'submit' => array(
'title' => $this->l('Save'),
),
),
);
}
/**
* Set values for the inputs.
*/
public function getConfigFormValues()
{
return array(
'YOUTUBEHOME_LINK_VIDEO' => Configuration::get('YOUTUBEHOME_LINK_VIDEO'),
);
}
/**
* Save form data.
*/
public function postProcess()
{
$form_values = $this->getConfigFormValues();
foreach (array_keys($form_values) as $key) {
Configuration::updateValue($key, Tools::getValue($key));
}
}
}
And here the error
My tpl file is in modules/youtubehome/views/templates/admin/youtubehome.tpl
I don't want to override the default form. Do you think i have doing something wrong ?
EDIT POST
Here it's the error with ps_version
try with :
$this->setTemplate('module:youtubehome/views/templates/admin/youtubehome.tpl');
Regards

Phalcon uniqueness on update

folks. The uniqueness validator in my form works as expected on adding new records, but on updating an exsisting record, it throws an error that the url already exists. It exists, in fact, but only in the current record.
Here is my controller:
$feed = Feeds::findFirst($id);
$feedForm = new FeedForm($feed, array('edit' => true));
if ($this->request->isPost() == true) {
$feedData = $this->request->getPost();
if ($feedForm->isValid($feedData, $feed)) {
if ($feed->save()) {
$this->flash->success("Feed successfuly updated.");
} else {
$this->flash->error("Update failed.");
}
} else {
foreach ($feedForm->getMessages() as $message) {
$this->flash->error($message);
}
}
}
And my form class:
class FeedForm extends FormBase {
public $options;
public function initialize($entity = null, $options = null) {
parent::initialize();
$this->setEntity($entity);
$this->options = $options;
$status = new Radio('status');
$status->addValidator(
new PresenceOf(
array(
'message' => 'The status is required.'
)
));
$this->add($status);
$name = new Text('name');
$name->addValidator(
new PresenceOf(
array(
'message' => 'The name is required.'
)
));
$name->addValidator(
new StringLength(
array(
'max' => 50,
'messageMaximum' => 'The name you entered is too long.'
)
));
$this->add($name);
$xml = new Text('xml');
$xml->addValidator(
new PresenceOf(
array(
'message' => 'The URL address is required.'
)
));
$xml->addValidator(
new StringLength(
array(
'max' => 2048,
'messageMaximum' => 'The URL address you entered is too long.'
)
));
$xml->addValidator(
new Url(
array(
'message' => 'The URL you entered is invalid.'
)
));
$xml->addValidator(
new Uniqueness(
array(
'model' => 'Sravnisite\Admin\Models\Feeds',
'table' => 'feeds',
'column' => 'xml',
'message' => 'The entered URL address already exists.'
)
));
$periodOptions = array();
for ($i = 4; $i <= 24; $i++) {
array_push($periodOptions, $i);
}
$this->add($xml);
$period = new Select('period', $periodOptions);
$period->addValidator(
new PresenceOf(
array(
'message' => 'The period is required.'
)
));
$this->add($period);
$shopID = new Select('shop_id', Shops::find(), array('using' => array('id', 'name')));
$shopID->addValidator(
new PresenceOf(
array(
'message' => 'The shop is required.'
)
));
$this->add($shopID);
}
}
Any ideas?
The form validation doesn't know to ignore the record you are updating - so for uniqueness it finds the record you're trying to update and gives an error. You could do some complicated find logic to keep the uniqueness validation in the form but it is better moved to the model. Your result would end up something like:
Controller
$feed = Feeds::findFirst($id);
$feedForm = new FeedForm($feed, array('edit' => true));
if ($this->request->isPost() == true) {
$feedData = $this->request->getPost();
if ($feedForm->isValid($feedData, $feed)) {
if ($feed->save()) {
$this->flash->success("Feed successfuly updated.");
} else {
$this->flash->error("Update failed.");
// Get each of the validation messages from the model
foreach ($feed->getMessages() as $message) {
$this->flash->error($message);
}
}
} else {
foreach ($feedForm->getMessages() as $message) {
$this->flash->error($message);
}
}
}
Form
// Exactly the same as you currently have but without the Uniqueness Validator
Model
class Feeds extends Phalcon\Mvc\Model
/**
* Validate that xml URLs are unique
*/
public function validation()
{
$this->validate(new Uniqueness(array(
"field" => "xml",
"message" => "The url must be unique."
)));
return $this->validationHasFailed() != true;
}

Basic Zend post workflow issue

I am new to this these technologies, so might not be asking to do this the easiest way, but: I want to create a form and ask for an ID value. Once submit is pressed, I want to take that ID, make an external XML call and then show the XML data. I am stuck on if I can do this in a single url:https://plesk.local:8443/modules/example/index.php/index/form. I would like to have both the form and the list data on the same page, so I can update the ID, press submit and see the new data...over and over...
I am trying to modify the basic "Example1" that Plesk includes. I can modify it and test it, but stuck on exactly how POST works. Ideally I want to have $this->view->form to have both a pm_Form_Simple and pm_View_List_Simple on the same $form view (if this makes sense).
So looking for help on
1) Can I use the same URL and handle the POST/GET from it
2) Can I have both a form and simple list on the same page?
thx!!!!!
Here is the sample controller:
<?php
class IndexController extends pm_Controller_Action
{
public function init()
{
parent::init();
// Init title for all actions
$this->view->pageTitle = 'Example Module';
// Init tabs for all actions
$this->view->tabs = array(
array(
'title' => 'Form',
'action' => 'form',
),
array(
'title' => 'List',
'action' => 'list',
),
);
}
public function indexAction()
{
// Default action will be formAction
$this->_forward('form');
}
public function formAction()
{
// Init form here
$form = new pm_Form_Simple();
$form->addElement('text', 'exampleText', array(
'label' => 'Example Text',
'value' => pm_Settings::get('exampleText'),
'required' => true,
'validators' => array(
array('NotEmpty', true),
),
));
$form->addControlButtons(array(
'cancelLink' => pm_Context::getModulesListUrl(),
));
if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
// Form proccessing here
pm_Settings::set('exampleText', $form->getValue('exampleText'));
$this->_status->addMessage('info', 'Data was successfully saved.');
$this->_helper->json(array('redirect' => pm_Context::getBaseUrl()));
}
# NEW - start
if (0)
{
# I want to be back here after the POST
# Want to show the list here after I take the POST parameter and do an external XML call...
$list = $this->_getListRandom();
$this->view->list = $list;
}
# NEW - end
$this->view->form = $form;
}
public function listAction()
{
$list = $this->_getListRandom();
// List object for pm_View_Helper_RenderList
$this->view->list = $list;
}
public function listDataAction()
{
$list = $this->_getListRandom();
// Json data from pm_View_List_Simple
$this->_helper->json($list->fetchData());
}
private function _getListRandom()
{
$data = array();
#$iconPath = pm_Context::getBaseUrl() . 'images/icon_16.gif';
for ($i = 0; $i < 15; $i++) {
$data[] = array(
'column-1' => '' . (string)rand() . '',
'column-2' => (string)rand(),
);
}
$list = new pm_View_List_Simple($this->view, $this->_request);
$list->setData($data);
$list->setColumns(array(
'column-1' => array(
'title' => 'Random with link',
'noEscape' => true,
),
'column-2' => array(
'title' => 'Random with image',
'noEscape' => true,
),
));
// Take into account listDataAction corresponds to the URL /list-data/
$list->setDataUrl(array('action' => 'list-data'));
return $list;
}
}
Yes
Yes
I'm not expirienced in zend, so it just try, I suggest to replace formAction() with following code:
public function formAction()
{
// Init form here
$form = new pm_Form_Simple();
$form->addElement('text', 'exampleText', array(
'label' => 'Example Text',
'value' => pm_Settings::get('exampleText'),
'required' => true,
'validators' => array(
array('NotEmpty', true),
),
));
$form->addControlButtons(array(
'cancelLink' => pm_Context::getModulesListUrl(),
));
if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getPost())) {
// Form proccessing here
pm_Settings::set('exampleText', $form->getValue('exampleText'));
$this->_status->addMessage('info', 'Data was successfully saved.');
$list = $this->_getListRandom();
$this->view->list = $list;
$this->view->form = $form;
// Redirects happens on next string, maybe you need to add something to getBaseUrl()
$this->_helper->json(array('redirect' => pm_Context::getBaseUrl()));
}
$this->view->form = $form;
}

$form->isValid says it is invalid, but my form does not show any error message - Zend Framework 2

Im having a problem with the addAction in my CRUD application. On the controller the logic does not pass the $form->isValid() verification but the form does not show any error message.
I tried with this (Thanks Sam):
foreach($form->get('product')->getElements() as $el)
{
echo $el->getName()." = ".$el->getValue()." > ".$el->getMessages()." <br/>";
}
That only show the name and value of the field, but not the error message.
I've tried letting the form totally blank and it fire "Value is required and can't be empty" error messages, but then, i fill each field one by one until i don't get more error messages but the form still invalid.
My form has a Product Fieldset as a base fieldset and a submit button. Inside Product Fieldset i have an ID field, a name field, a price field and a Brand Fieldset. Inside my Brand Fieldset i have a id field. Like this:
ProductForm:
class ProductForm extends Form
{
public function init()
{
// we want to ignore the name passed
parent::__construct('product');
$this->setName('product');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'product',
'type' => 'Administrador\Form\ProductFieldset',
'options' => array(
'use_as_base_fieldset' => true
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Add',
'id' => 'submitbutton',
),
));
}
}
ProductFieldset:
class ProductFieldset extends Fieldset implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
function __construct($name = null)
{
parent::__construct('product_fieldset');
$this->setHydrator(new ArraySerializableHydrator());
$this->setObject(new Product());
}
public function init()
{
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
));
$this->add(array(
'name' => 'name',
'type' => 'Text',
'options' => array(
'label' => 'Name',
),
));
$this->add(array(
'name' => 'price',
'type' => 'Text',
'options' => array(
'label' => 'Price',
),
));
$this->add(array(
'name' => 'brand',
'type' => 'BrandFieldset',
));
}
public function setServiceLocator(ServiceLocatorInterface $sl)
{
$this->serviceLocator = $sl;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
BrandFieldset:
class BrandFieldset extends Fieldset
{
function __construct(BrandTable $brandTable)
{
parent::__construct('brand_fieldset');
//$this->setHydrator(new ClassMethodsHydrator(false))->setObject(new Brand());
$this->setHydrator(new ArraySerializableHydrator());
$this->setObject(new Brand());
$brandSelectOptionsArray = $brandTable->populateSelectBrand();
$this->add(array(
'name' => 'id',
'type' => 'Select',
'options' => array(
'label' => 'Brand',
'empty_option' => 'Please select a brand',
'value_options' => $brandSelectOptionsArray,
),
));
}
}
This is my new Form statement in the addAction:
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('Administrador\Form\ProductForm');
Inside my model 'Product' i have the inputFilters, required filter for 'id' field, required filter for 'name' field. And for the Brand field i created other inputFilter and added it to the main inputFilter:
$brandFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'filters' => array(
array('name' => 'Int'),
),
)));
$inputFilter->add($brandFilter, 'brand');
The weird behavior is that my editAction works fine and has the same logic.
Is it there any form of echoing an internal error message from the form, something that helps me to understand WHY the form is not valid.
EDIT 2013-06-01
Here is my full Controller:
class ProductController extends AbstractActionController
{
protected $productTable;
protected $brandTable;
public function indexAction()
{
return new ViewModel(array(
'products' => $this->getProductTable()->fetchAll(),
));
}
public function addAction()
{
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('Administrador\Form\ProductForm');
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost()) {
$product = new Product();
$product->brand = new Brand();
$form->setInputFilter($product->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$product->exchangeArray($form->getData());
$this->getProductTable()->saveProduct($product);
// Redirect to list of products
return $this->redirect()->toRoute('product');
}
}
return new ViewModel(array(
'form' => $form,
));
}
public function editAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('product', array(
'action' => 'add'
));
}
// Get the Product with the specified id. An exception is thrown
// if it cannot be found, in which case go to the index page.
try {
$product = $this->getProductTable()->getProduct($id);
}
catch (\Exception $ex) {
return $this->redirect()->toRoute('product', array(
'action' => 'index'
));
}
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('Administrador\Form\ProductForm');
$brand = $this->getBrandTable()->getBrand($product->brand);
$product->brand = $brand;
$form->bind($product);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setInputFilter($product->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getProductTable()->saveProduct($form->getData());
// Redirect to list of products
return $this->redirect()->toRoute('product');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
public function deleteAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('product');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->getPost('del', 'No');
if ($del == 'Yes') {
$id = (int) $request->getPost('id');
$this->getProductTable()->deleteProduct($id);
}
// Redirect to list of products
return $this->redirect()->toRoute('product');
}
return array(
'id' => $id,
'product' => $this->getProductTable()->getProduct($id)
);
}
public function getProductTable()
{
if (!$this->productTable) {
$sm = $this->getServiceLocator();
$this->productTable = $sm->get('Administrador\Model\ProductTable');
}
return $this->productTable;
}
public function getBrandTable()
{
if (!$this->brandTable) {
$sm = $this->getServiceLocator();
$this->brandTable = $sm->get('Administrador\Model\BrandTable');
}
return $this->brandTable;
}
}
My case was I passed wrong input filter. isValid returns false, but $form->getMessages() is empty. Form OrderForm had the following:
$form->setInputFilter(new \Application\Form\UserInputFilter($er));
When I changed UserInputFilter to OrderInputFilter it works.
Well, I got the answer :D
This is how the addAction should be:
public function addAction()
{
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('Administrador\Form\ProductForm');
$form->get('submit')->setValue('Add');
$product = new Product();
$product->brand = new Brand();
$form->bind($product); // I need to bind the product to the form to pass the isValid() validation
$request = $this->getRequest();
if ($request->isPost()) {
$form->setInputFilter($product->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$product = $form->getData();
$this->getProductTable()->saveProduct($product);
// Redirect to list of products
return $this->redirect()->toRoute('product');
}
}
return new ViewModel(array(
'form' => $form,
));
}
Apparently i needed to bind and empty product object to the form to be able to pass the isValid() validation. After that i retrieve a product object from the $form->getData().
You can also do: $form->setBindOnValidate(false);

zend array[] element with validator

hello i have a form where the user can click on a button and dinamically add new elements(with Jquery)
<input name="sconto[]" type="text"><br>
<input name="sconto[]" type="text"><br>
<input name="sconto[]" type="text"><br>
...
I have a custom validator for float numbers in format with comma and dot separation like 20.50 and 20,50
The problem is i can't seem to find how to make zend apply it it to each element of the array.
So how should i declare this element and how to apply the validator? xD
this is my validator
protected $_messageTemplates = array(
self::NON_E_NUMERO => 'non sembra essere un numero'
);
public function isValid($value, $context = null)
{
$pos_virgola = strpos($value, ",");
if ($pos_virgola !== false)
$value = str_replace(",", ".", $value);
if (!is_numeric($value))
{
$this->_error(self::NON_E_NUMERO, $value);
return false;
}
else
return true;
}
}
the form i don't know how to do it, i use this but obviously it doesn't work
$sconto = $this->createElement('text','sconto')->setLabel('sconto');
//->setValidators(array(new Gestionale_Validator_Float()));
$this->addElement($sconto);
...
$sconto->setDecorators(array(//no ViewHelper
'Errors',
'Description',
array(array('data' => 'HtmlTag'), array('tag' => 'td', /*'class' => 'valore_campo', */'id'=>'sconto')),
array('TdLabel', array('placement' => 'prepend', 'class' => 'nome_campo'))
));
If Marcin comment is not what you want to do, then this is another way to create multi text element.
Create a custom decorator 'My_Form_Decorator_MultiText'. You will need to register your custom decorator class. Read Zend Framework doc for details http://framework.zend.com/manual/en/zend.form.decorators.html
class My_Form_Decorator_MultiText extends Zend_Form_Decorator_Abstract {
public function render($content) {
$element = $this->getElement();
if (!$element instanceof Zend_Form_Element_Text) {
return $content;
}
$view = $element->getView();
if (!$view instanceof Zend_View_Interface) {
return $content;
}
$values = $element->getValue();
$name = $element->getFullyQualifiedName();
$html = '';
if (is_array($values)) {
foreach ($values as $value) {
$html .= $view->formText($name, $value);
}
} else {
$html = $view->formText($name, $values);
}
switch ($this->getPlacement()) {
case self::PREPEND:
return $html . $this->getSeparator() . $content;
case self::APPEND:
default:
return $content . $this->getSeparator() . $html;
}
}
}
Now your validation class will validate each element value
class My_Validate_Test extends Zend_Validate_Abstract {
const NON_E_NUMERO = 'numero';
protected $_messageTemplates = array(
self::NON_E_NUMERO => 'non sembra essere un numero'
);
public function isValid($value, $context = null) {
if (!is_numeric($value)) {
$this->_error(self::NON_E_NUMERO, $value);
return false;
}
else
return true;
}
}
This is how you can use the new decorator
$element = new Zend_Form_Element_Text('sconto', array(
'validators' => array(
new My_Validate_Test(),
),
'decorators' => array(
'MultiText', // new decorator
'Label',
'Errors',
'Description',
array('HtmlTag', array('tag' => 'dl',))
),
'label' => 'sconto',
'isArray' => true // must be true
));
$this->addElement($element);
Hope this helps