How to make a field that is an entity as hidden in the form with SonataAdmin? - forms

I need to add entity field as a hidden in my form
In the admin form with sonata I have:
protected function configureFormFields(FormMapper $formMapper)
{
if ($this->getRoot()->getSubject()->getId()) {
$formMapper
->add('driverNight', 'hidden', array(), array('admin_code' => 'cab.admin.driver'))
->add('monday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Monday', 'value' => '0'))
->add('tuesday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Tuesday', 'value' => '0'))
->add('wednesday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Wednesday', 'value' => '0'))
->add('thursday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Thursday', 'value' => '0'))
->add('friday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Friday', 'value' => '0'))
->add('saturday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Saturday', 'value' => '0'))
->add('sunday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Sunday', 'value' => '0'))
}
Actually, no value in the input (see the inspect image)
How to make the driverNight field as hidden knowing that it is of type entity?

You could use a data transformer as detailed here: data transformer
I suggest that you create a transformer class which transforms the entity to an int in the view layer and reverses from int to entity in the model layer and the use the addModelTransformer method in your config form.
Create the model Transformer class which implements Symfony\Component\Form\DataTransformerInterface and contains 2 methods transform and reverseTransform. This class could be constructed by passing 2 arguments: Entity manager and the user entity object that will be transformed to int.
.
class DriverToIntTransformer implements DataTransformerInterface {
private $manager;
private $driver;
public function __construct(ObjectManager $manager, $oUser)
{
$this->manager = $manager;
$this->driver = $oUser;
}
public function transform($user)
{
if (null === $user) {
return $this->driver->getId();
}
return $user->getId();
}
public function reverseTransform($driverNumber)
{
if (!$driverNumber) {
return;
}
$oDriver = $this->manager
->getRepository('YourUserBundle:User')
// query for the driver with this id
->find($driverNumber);
if (null === $oDriver) {
throw new TransformationFailedException(sprintf(
'An user with number "%s" does not exist!',
$driverNumber
));
}
return $oDriver;
}
2 call the transform method:
if ($this->getRoot()->getSubject()->getId()) {
$driver = $this->getRoot()->getSubject()->getId();
$em = $this->container->get('doctrine.orm.entity_manager');
$oDriver = $em->getRepository('YourUserBundle:User')->find($driver);
$formMapper
->add('driverNight', 'hidden', array(), array('admin_code' => 'cab.admin.driver'));
$formBuilder = $formMapper->getFormBuilder();
$formBuilder->get('driverNight')->addModelTransformer(new DriverToIntTransformer($em, $oDriver));
$formMapper
->add('monday', 'checkbox', array('required' => false, "attr" => array('class' => 'checkbox-day'), 'label' => 'Monday', 'value' => '0'));//.....
}

Related

Add form error to a repeated FormType in Controller

I'm trying to add an error to a mail field of type repeated:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('lastname', 'text', array(
'required' => true,
'trim' => true,
'max_length' => 255,
'attr' => array('placeholder' => 'lastname',
)
))
->add('mail', 'repeated', array(
'type' => 'email',
'label' => 'email',
'invalid_message' => 'Les Emails doivent correspondre',
'options' => array('required' => true),
'first_options' => array('label' => 'email',
'attr' => array('placeholder' => 'ph_mail_first',
)),
'second_options' => array('label' => 'emailvalidation',
'attr' => array('placeholder' => 'ph_mail_second',
'requiered' => true
)),
'required' => true,
'trim' => true
))
}
public function getName()
{
return 'AddUser';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => true,
));
}
And this what I'm doing in my controller:
$sMessage = $this->container->get('translator')->trans('error');
$oForm->get('mail')->addError(new \Symfony\Component\Form\FormError($sMessage));
This method is working with the other fields except for this one, the error message does not appear. I also tried with
get('mail.first') and get('mail.first_options')
This works fine:
$sMessage = $this->container->get('translator')->trans('error');
$oForm->get('lastname')->addError(new \Symfony\Component\Form\FormError($sMessage));
I managed to find a workaround. I honestlty don't know if this is the right solution but it can help someone stuck with this problem.
$oForm['mail']['first']->addError(new \Symfony\Component\Form\FormError($sMessage));
$oForm->get('mail')->get('first')

Prestashop HelperFrom/List - messy layout

I'm new to prestashop and I worked the whole day on creating a back office interface that allows the user to write, edit, and delete articles. It is sort of a blog. I used Prestashop's Helpers (Form and List) and everything works great. I also added a new tab in the back office to access this tool.
The problem is that the layout is messy and doesn't look like the other forms and listing pages. The layout is really not sexy. Maybe I should look at some css file, or add any function in my controller ? You'll find the source code of the latter here (I can't insert images, not enough reputation --'):
<?php
class Article extends ObjectModel
{
/** #var string Name */
public $id_article;
public $titre;
public $contenu;
public $url_photo;
/**
* #see ObjectModel::$definition
*/
public static $definition = array(
'table' => 'article',
'primary' => 'id_article',
'fields' => array(
'titre' => array(
'type' => self::TYPE_STRING,
'validate' => 'isGenericName',
'required' => true,
'class' => 'lg'
),
'contenu' => array(
'type' => self::TYPE_STRING,
'validate' => 'isGenericName',
'required' => true
),
'url_photo' => array(
'type' => self::TYPE_STRING,
'validate' => 'isGenericName',
'required' => false,
),
),
);
}
class AdminBlogController extends AdminController{
public function initContent(){
parent::initContent();
}
public function __construct(){
$this->table = 'article';
$this->className = 'Article';
$this->lang = false;
// Building the list of records stored within the "article" table
$this->fields_list = array(
'id_article' => array(
'title' => 'ID',
'align' => 'center',
'width' => 25
),
'titre' => array(
'title' => 'Titre',
'width' => 'auto'
),
'contenu' => array(
'title' => 'Contenu',
'width' => 'auto'
)
);
// This adds a multiple deletion button
$this->bulk_actions = array(
'delete' => array(
'text' => $this->l('Delete selected'),
'confirm' => $this->l('Delete selected items?')
)
);
parent::__construct();
}
// This method generates the list of results
public function renderList(){
// Adds an Edit button for each result
$this->addRowAction('edit');
// Adds a Delete button for each result
$this->addRowAction('delete');
return parent::renderList();
}
// This method generates the Add/Edit form
public function renderForm(){
// Building the Add/Edit form
$this->fields_form = array(
'tinymce' => true,
'legend' => array(
'title' => 'Article'
),
'input' => array(
array(
'type' => 'text',
'label' => 'Titre',
'name' => 'titre',
'class' => 'lg',
'required' => true,
//'desc' => 'Nom de l\'article',
),
array(
'type' => 'textarea',
'label' => 'Contenu',
'name' => 'contenu',
'class' => 'lg',
'required' => true,
'autoload_rte' => true,
//'desc' => 'Contenu de l\'article',
),
array(
'type' => 'file',
'label' => 'Photo',
'name' => 'url_photo',
'class' => 'lg',
'required' => true,
//'desc' => 'Contenu de l\'article',
)
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
return parent::renderForm();
}
}
?>
Thank you.
I just needed to set $this->bootstrap = true

ZF2 - Binding Nested Fieldsets/Collections

I have two entities (Metaproduct and Options) that have Many-To-Many Unidirectional relation with entity Specification.
The relation between Metaproduct and Option is One-To-Many.
The code for the Fieldsets and Forms for Metaproduct is the following:
MetaproductFieldset.php
namespace Bundle\Fieldset;
class MetaproductFieldset extends EntityUsingFieldset implements InputFilterProviderInterface{
...
public function __construct(ObjectManager $objectManager)
{
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'options',
'options' => array(
'label' => 'Options',
'count' => 1,
'allow_add' => true,
'allow_remove' => true,
'should_create_template' => true,
'target_element' => new OptionFieldset($objectManager),
),
'attributes' => array(
'id' => 'options',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'specifications',
'options' => array(
'label' => 'Specifications',
'count' => 1,
'allow_add' => true,
'allow_remove' => true,
'should_create_template' => true,
'target_element' => new SpecificationFieldset($objectManager),
),
'attributes' => array(
'id' => 'specifications',
),
));
OptionFieldset.php
namespace Bundle\Fieldset;
class OptionFieldset extends EntityUsingFieldset implements InputFilterProviderInterface{
public function __construct(ObjectManager $objectManager)
{
$this->setObjectManager($objectManager);
parent::__construct('option');
$this->setHydrator(new DoctrineHydrator($objectManager))->setObject(new \Bundle\Entity\Option());
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'specifications',
'options' => array(
'label' => 'Specifications',
'count' => 1,
'allow_add' => true,
'allow_remove' => true,
'should_create_template' => true,
'target_element' => new SpecificationFieldset($objectManager),
),
'attributes' => array(
'id' => 'specifications',
),
));
SpecificationFieldset.php
namespace Bundle\Fieldset;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\InputFilter\InputFilterProviderInterface;
class SpecificationFieldset extends EntityUsingFieldset implements InputFilterProviderInterface{
public function __construct(ObjectManager $objectManager)
{
$this->setObjectManager($objectManager);
parent::__construct('specification');
$this->setHydrator(new DoctrineHydrator($objectManager))->setObject(new \Bundle\Entity\Specification());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'label',
'options' => array(
'label' => 'Label',
'object_manager' => $objectManager,
'target_class' => 'Bundle\Entity\Label',
'property' => 'value',
'empty_option' => '--- please choose ---'
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'value',
'options' => array(
'label' => 'Value'
)
));
}
Metaproduct.php
namespace Bundle\Form;
...
class Metaproduct extends Form {
public function __construct(ObjectManager $objectManager){
parent::__construct('metaproduct-form');
$this->setHydrator(new DoctrineHydrator($objectManager));
$mpFieldset = new MetaproductFieldset($objectManager);
$mpFieldset->setUseAsBaseFieldset(true);
...
But when I try to print bind an object on that form, the following Expection is throwed:
File
zendframework\library\Zend\Form\Fieldset.php:439
Message
Zend\Form\Fieldset::setObject expects an object argument; received "Array"
Trace
#0 C:\projects\acuradoria-zend\vendor\zendframework\zendframework\library\Zend\Form\Element\Collection.php(549): Zend\Form\Fieldset->setObject(Array)
#1 C:\projects\acuradoria-zend\vendor\zendframework\zendframework\library\Zend\Form\Fieldset.php(601): Zend\Form\Element\Collection->extract()
#2 C:\projects\acuradoria-zend\vendor\zendframework\zendframework\library\Zend\Form\Form.php(854): Zend\Form\Fieldset->extract()
#3 C:\projects\acuradoria-zend\vendor\zendframework\zendframework\library\Zend\Form\Form.php(292): Zend\Form\Form->extract()
#4 C:\projects\acuradoria-zend\module\Bundle\src\Bundle\Controller\Plugin\FormService.php(42): Zend\Form\Form->bind(Object(Bundle\Entity\Metaproduct))
Please see this issue:
Problems in nested collections and fieldsets
https://github.com/zendframework/zf2/issues/5640

ZF2 populate form collections element with child objects

Based on the Zend Framework 2 manual (here) I made a form like this:
class ParentForm extends Form
{
public function init()
{
$this->setName('parent_form')
->setAttribute('method', 'post')
->setHydrator(new ClassMethods(true))
->setInputFilter(new InputFilter());
$this->add(array(
'type' => 'Application\Form\Fieldset\Parent',
'name' => 'parent',
'options' => array(
'label' => 'Parent',
'use_as_base_fieldset' => true
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf'
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Send'
)
));
}
}
And the 'parent' fieldset:
class ParentFieldset extends Fieldset
{
protected $count = 2;
public function init()
{
$this->setName('parent_fieldset')
->setHydrator(new ClassMethodsHydrator(false))
->setObject(new Model\Parent());
$this->add(array('type' => 'Element\MyField'));
$this->add(array(
'type' => 'collection',
'name' => 'children',
'options' => array(
'label' => 'Children',
'count' => $this->count,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Application\Form\Fieldset\Child',
'name' => 'child',
'options' => array(
'label' => child',
),
),
)
));
}
public function setCount($count)
{
$this->count = max($count, 2);
}
}
This works great to hydrate my Parent object with data obtained from my form. A var_dump of the resuting object will look like:
object(Parent)
public myField => foo
public children =>
array =>
0 => object(Child)
public field1 => value1
public field2 => value2
....
1 => object(Child)
.....
2 => object(Child)
.....
But I cannot figure out how to populate this multi-dimensional form with the above object if hydrated from the database (for editing purposes). How can I do that?
Note: the count property in the form is set to the same number of children as in the object.

ZF2 form as array

I'd like to create a simple zend form with a few fields but i wanna collect this fields into an array. I'd like to see my form names like this:
name="login[username]" name="login[password]" name="login[submit]"
I wasn't able to find any description. If somebody knows the solution please let me know!
You can try with fieldsets like that
namespace Application\Form;
use Application\Entity\Brand;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class YourFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct()
{
parent::__construct('login');
$this->add(array(
'name' => 'username',
'options' => array(
'label' => 'Username'
),
'attributes' => array(
'required' => 'required'
)
));
$this->add(array(
'name' => 'password',
'type' => 'Zend\Form\Element\Password',
'options' => array(
'label' => 'Password'
),
'attributes' => array(
'required' => 'required'
)
));
$this->add(array(
'name' => 'submit',
'type' => 'Zend\Form\Element\Submit',
'options' => array(
'label' => 'Submit'
),
'attributes' => array(
'required' => 'required'
)
));
}
/**
* #return array
*/
public function getInputFilterSpecification()
{
return array(
'name' => array(
'required' => true,
)
);
}
}