I am currently playing around with ZF2 beta 4 and I seem to be stuck when i try to use fieldsets within a form and getting the data back into the form when the form is submitted. I am not sure if I am not setting the input filters right for fieldsets or I am missing something. For example, I have the following (simplified to make it clear):
Controller
public function indexAction(){
$form = new MyForm();
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->post());
if ($form->isValid()) {
//Do something
print_r($form->getData()); //for debug
}
}
return array('form' => $form);
}
MyForm.php
class MyForm extends Form
{
public function __construct()
{
parent::__construct();
$this->setName('myForm');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'title',
'attributes' => array(
'type' => 'text',
'label' => 'Title',
),
));
$this->add(new MyFieldset('myfieldset'));
//setting InputFilters here
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'title',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
)));
//Now add fieldset Input filter
foreach($this->getFieldsets() as $fieldset){
$fieldsetInputFilter = $factory->createInputFilter($fieldset->getInputFilterSpecification());
$inputFilter->add($fieldsetInputFilter,$fieldset->getName());
}
//Set InputFilter
$this->setInputFilter($inputFilter);
}
}
MyFieldset.php
class MyFieldset extends Fieldset implements InputFilterProviderInterface{
public function __construct($name)
{
parent::__construct($name);
$factory = new Factory();
$this->add($factory->createElement(array(
'name' => $name . 'foo',
'attributes' => array(
'type' => 'text',
'label' => 'Foo',
),
)));
}
public function getInputFilterSpecification(){
return array(
'foo' => array(
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
),
);
}
}
I am able to output the form as expected and I end up with two input elements named 'title' and 'myfieldsetfoo' (the name given when outputing with the ViewHelper). So of course when I submit the raw post will show values for 'title' and 'myfieldsetfoo'. However, when I use SetData() the values for the field set are not being populated (although I can see the values in the raw post object). Instead, examining the output of '$form->getData()' I receive:
Array(
[title] => Test,
[myfieldset] => Array(
[foo] =>
)
)
What am I missing? What do I need to do so that ZF2 understands how to populate the fieldset?
Thanks for any help, this is driving me crazy.
Why I do is concatenate InputFilter so I could handle the whole HTML form array posted.
<form method="POST">
<input type="text" name="main[name]" />
<input type="text" name="main[location]" />
<input type="text" name="contact[telephone]" />
<input type="submit" value="Send" />
</form>
This will create an array posted like
post["main"]["name"]
post["main"]["location"]
post["contact"]["telephone"]
Filtered and validated with:
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
$post = $this->request->getPost();
$inputFilter = new InputFilter();
$factory = new InputFactory();
// $post["main"]
$mainFilter = new InputFilter();
$mainFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$mainFilter->add($factory->createInput(array(
'name' => 'location',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$inputFilter->add($mainFilter, "main");
// $post["contact"]
$contactFilter = new InputFilter();
$contactFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$contactFilter->add($mainFilter, "contact");
//Set posted data to InputFilter
$inputFilter->setData($post->toArray());
http://www.unexpectedit.com/zf2/inputfilter-validate-and-filter-a-form-data-with-fieldsets
I think you forgot to prepare your form in the controller:
return array('form' => $form->prepare());
This will rename the "name" field of your fieldset to "myfieldset[foo]", so you don't have to prepend the fieldsets name on your own.
Just use
'name' => 'foo'
instead of
'name' => $name . 'foo'
in your fieldset class.
I think the problem is that you declare a new form in your controller. And that clear the previous form.
$form = new MyForm();
I use the Service Manager to declare the form and filters.
And then in the controller I do:
$form = $this->getServiceLocator()->get('my_form');
That way I always get the object I want
Update
I no longer use service manager to call forms. I just call a new form and issue $form->setData($data);
The source for the data can also be entity though then I would issue: $form->bind($entity)
Related
guys (and ladies)
I like to ask you how to build the forms (formbuilder) in Prestashop 1.7 for the current 2020 year.
I created module with classes and hooks, but I can't find the info on how to create forms via "classes" and "controllers".
I'd happy to have something like this:
What have already done:
created custom module
created custom hook
custom .tpl from /module/templates/front/custom.tpl is added to the hook and displays data correctly.
Using form builder in your .php file (or controller)
return array(
'form' => array(
'legend' => array(
'title' => $this->l('Settings'),
'icon' => 'icon-cogs',
),
'input' => array(
array(
'type' => 'switch',
'label' => $this->l('Live mode'),
'name' => 'TESTONE_LIVE_MODE',
'is_bool' => true,
'desc' => $this->l('Use this module in live mode'),
'values' => array(
array(
'id' => 'active_on',
'value' => true,
'label' => $this->l('Enabled')
),
array(
'id' => 'active_off',
'value' => false,
'label' => $this->l('Disabled')
)
),
),
array(
'col' => 3,
'type' => 'text',
'prefix' => '<i class="icon icon-envelope"></i>',
'desc' => $this->l('Enter a valid email address'),
'name' => 'TESTONE_ACCOUNT_EMAIL',
'label' => $this->l('Email'),
),
array(
'type' => 'password',
'name' => 'TESTONE_ACCOUNT_PASSWORD',
'label' => $this->l('Password'),
),
),
'submit' => array(
'title' => $this->l('Save'),
),
),
);
}
I want to change the URL of cancel button presently on canceling the page it is showing me the list but I want to redirect the user on the cancel button.
public function renderForm() {
$this->fields_form = array(
'legend' => array('title' => $this->l('Additional Service'), 'icon' => 'icon-cogs'),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('id_citydelivery'),
'name' => 'id_citydelivery',
'size' => 255),
array(
'type' => 'text',
'label' => $this->l('Service_name'),
'name' => 'service_name',
'size' => 255,
'required' => true,
'desc' => $this->l('Enter name of Arrival port')
),
array(
'type' => 'switch',
'label' => $this->l('Active'),
'name' => 'active',
'required' => false,
'is_bool' => true,
'values' => array(array(
'id' => 'active_on',
'value' => 1,
'label' => $this->l('Active')), array(
'id' => 'active_off',
'value' => 0,
'label' => $this->l('Inactive')))),
),
'submit' => array('title' => $this->l('Save')),
);
return parent::renderForm();
}
After Diving into the code I came to know back button URL is set it by $_post['Back']
So I have overridden it; you have to change # with your URL
public function postProcess() {
if (Tools::getIsset('submitAddadditional_service')) {
$this->redirect_after = Context::getContext()->link->getAdminLink('AdminGCardeliverycity', true) . '&updatecitydelivery&id_citydelivery=' . Tools::getValue('id_citydelivery');
} else {
$_POST['back'] = '#'; //For Cancel button url on form which is genrated by renderform()
}
parent::postProcess();
}
i want to show already selected values in tags of ESelected extension but unable to find any solution my code in update form in view is
$this->widget('ext.select2.ESelect2', array(
'name' => 'cat_names[]',
'data' => Coupon::getCategories(),
'options' => array(
'placeholder' => '',
'allowClear' => true,
),
'htmlOptions' => array(
'multiple' => 'multiple',
),
));
if i add tags fields in option of Eselect it changes the behaviour and stop working i add tags in options like this
'tags' => Coupon::getCategories_old(),
Any suggestion will be helpfull thanks in advance
$this->widget('ext.select2.ESelect2', array(
'name' => 'cat_names[]',
'value'=> array(91,95),
'data' => Coupon::getCategories(),
'options' => array(
'placeholder' => '',
'allowClear' => true,
),
'htmlOptions' => array(
'multiple' => 'multiple',
),
));
I am trying to get the filtering to run although I am having some issues below is my view note that this in in a PARTIAL view :-
If I click on the header of the column it does the sorting as expected, however if I select an option from the dropdown it doesn't filter the items...
Any ideas?
<?php
$myuser = new Myuser('search');
$filterBtn = $this->widget('bootstrap.widgets.TbButton', array(
'icon' => 'filter',
'size' => 'small',
'label' => $myuser->paging ? 'View All' : 'View Less',
'htmlOptions' => array('class'=>'pull-right', 'style'=> 'margin:20px 0;'),
'url' => $myuser->paging ? array('/carrot/myuser/admin/paging/0') : array('/carrot/myuser/admin')
), true);
$this->widget('bootstrap.widgets.TbGridView',array(
'id' => 'myuser-grid','type'=>'striped bordered condensed',
'dataProvider' => $myuser->search(),
'filter' => $myuser,
'columns' => array(
array(
'id' => 'user_id',
'class' => 'CCheckBoxColumn',
'checked' => 'in_array($data->user_id, $this->grid->owner->model->student_ids)',
'checkBoxHtmlOptions' => array(
'name' => 'selected_student_id[]',
)
),
'firstname',
'surname',
'username',
array(
'name' => 'year_id',
'filter' => CHtml::activeDropDownList($myuser, 'year_id', CHtml::listData(Organisation::model()->distinctYears, 'year_id', 'year_id'), array('prompt'=>'All Years')),
'htmlOptions' => array('style' => 'text-align:center;'),
'headerHtmlOptions' => array('style' => 'text-align:left;'),
),
array(
'name' => 'form_name',
'header' => 'Form',
'filter' => CHtml::activeDropDownList($myuser, 'form_name', CHtml::listData(Organisation::model()->distinctForms, 'form_name', 'form_name'), array('prompt'=>'All Forms')),
),
array(
'name' => 'House',
'filter' => CHtml::activeDropDownList($myuser, 'House', CHtml::listData(Organisation::model()->distinctHouses, 'House', 'House'), array('prompt'=>'All Houses')),
),
),
)); ?>
My model has the following search() method:
public function search($limit = false)
{
$criteria = new CDbCriteria();
$criteria->compare('t.user_id',$this->user_id,true);
$criteria->compare('t.firstname',$this->firstname,true);
$criteria->compare('t.surname',$this->surname,true);
$criteria->compare('t.username',$this->username,true);
$criteria->compare('t.year_id',$this->year_id);
$criteria->compare('t.form_name',$this->form_name);
$criteria->compare('t.House',$this->House);
$criteria->compare('o.organisation_id',$this->organisation_id);
$criteria->group = 't.user_id';
$criteria->together = true;
return new CActiveDataProvider($this->currentUserOrganisation(), array(
'criteria' => $criteria,
'pagination' => array(
'pageSize' => $this->paging ? ($limit) ? $limit : OverviewController::PAGE_SIZE : 2000
),
'sort' => array(
'defaultOrder' => array('firstname'=>false, 'surname'=>false),
'attributes' => array(
'organisation_name' => array(
'asc' => 'organisation_name',
'desc' => 'organisation_name DESC',
'default' => 'desc',
),
'*'
)
),
));
}
I think you can't use a DropDownList as filter, but you can easily use CHTML::listData():
array(
'name' => 'year_id',
'filter' => CHtml::listData(Organisation::model()->distinctYears, 'year_id', 'year_id'),
'htmlOptions' => array('style' => 'text-align:center;'),
'headerHtmlOptions' => array('style' => 'text-align:left;'),
),
array(
'name' => 'form_name',
'header' => 'Form',
'filter' => CHtml::listData(Organisation::model()->distinctForms, 'form_name', 'form_name'),
),
array(
'name' => 'House',
'filter' => CHtml::listData(Organisation::model()->distinctHouses, 'House', 'House'),
),
This will automatically generate a DropDownList for you.
I hope this works for you.
I created new AdminReferenceController in prestashop back office with list and form for every item in list, and everything is working fine except one thing. When i try show image below upload button image is not displayed, (i check, image exist on server and url is valid). I use prestashop 1.5.6.0 Please check what i am doing wrong? Name and description values is properly displayed...
public function renderForm()
{
$this->fields_form = array(
'tinymce' => true,
'legend' => array(
'title' => $this->l('Reference'),
'image' => '../modules/reference/logo.gif'
),
'input' => array(
array(
'type' => 'text',
'lang' => false,
'label' => $this->l('Reference name:'),
'name' => 'name',
'size' => 60,
'desc' => $this->l('Reference name')
),
array(
'type' => 'file',
'lang' => false,
'label' => $this->l('Reference image:'),
'name' => 'image',
'display_image' => true,
'desc' => $this->l('Upload Reference image from your computer')
),
array(
'type' => 'textarea',
'label' => $this->l('Reference description:'),
'name' => 'description',
'autoload_rte' => true,
'desc' => $this->l('Reference description')
)
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
if (!($obj = $this->loadObject(true)))
return;
$this->fields_value = array(
'image' => "<img src='/prestashop/img/reference/1.jpg'>",
'size' => '500',
'name' => 'test',
'description' => 'test'
);
return parent::renderForm();
}
Thanks
You can also use this code if it helps you
public function renderForm()
{
if (!($obj = $this->loadObject(true)))
return;
$image = _PS_MANU_IMG_DIR_.$obj->id.'.jpg';
$image_url = ImageManager::thumbnail($image, $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350,
$this->imageType, true, true);
$image_size = file_exists($image) ? filesize($image) / 1000 : false;
$this->fields_form = array(
'legend' => array(
'title' => $this->l('Add Maker'),
'icon' => 'icon-maker'
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('Name'),
'name' => 'name',
'required' => true
),
array(
'type' => 'file',
'label' => $this->l('Maker Image'),
'name' => 'image_url_maker',
'image' => $image_url ? $image_url : false,
'size' => $image_size,
'display_image' => true,
'col' => 6,
'hint' => $this->l('Upload a maker image from your computer.')
),
),
'submit' => array(
'title' => $this->l('Save'),
)
);
return parent::renderForm();
}