Symfony2 Option values on ChoiceList - php

I'm trying to set custom values for Select Options using Form types and 'choice_list'.
Type:
->add('status', 'choice', array(
'constraints' => array(
new Assert\NotBlank(array('message' => 'Required field missing: status'))
),
'error_bubbling' => true,
'choice_list' => new StatusChoiceList()
StatusChoiceList file:
class StatusChoiceList extends LazyChoiceList
{
/**
* Loads the choice list
*
* Should be implemented by child classes.
*
* #return ChoiceListInterface The loaded choice list
*/
protected function loadChoiceList()
{
$array = array(
'Preview' => 'Preview',
'Hidden' => 'Hidden',
'Live' => 'Live'
);
$choices = new ChoiceList($array, $array);
return $choices;
}
}
the select tag have a wrong values 0,1,2 and a good labels

ChoiceList class used for choices of arbitrary data types. In your case you should use SimpleChoiceList instead. First parameter is an array with choices as keys and labels as values.
protected function loadChoiceList()
{
$array = array(
'Preview' => 'Preview',
'Hidden' => 'Hidden',
'Live' => 'Live'
);
$choices = new SimpleChoiceList($array);
return $choices;
}

Related

How to load select option from database in zf2

I Have been following zf2 guide for blog I have created everything Controller, Factory, Form, Mapper, Model, Service, view etc
In my form I have a select element
$this->add(array(
'type' => 'select',
'name' => 'roleId',
'attributes' => array(
'id' => 'roleId',
'options' => array(
'1' => 'Admin',
'2' => 'Manager',
),
),
'options' => array(
'label' => 'Role',
),
));
Now in this form I want to load the option for the role from the database.
I tried loading the option by creating a simple function, which can be accessed in the element as below, but Am not able to fetch the result. I have already created Controller, Factory, Form, Mapper, Model, Service and view, Where I can do CRUD operation on Role.
$this->add(array(
'type' => 'select',
'name' => 'roleId',
'attributes' => array(
'id' => 'roleId',
'options' => $this->getAllRoles(),
),
'options' => array(
'label' => 'Role',
),
));
public function getAllRoles()
{
$roles = $this->getServiceLocator()->get('Admin\Service\RoleService');
$allRoles = $this->getAllTheRoles();
return $allroles;
}
Can anybody guide me how can I load all the Roles in option as listed in the IndexAction following Blog Post with ID and Name of the Role.
You could create a reusable form element that is pre-populated with the roles. To do so you must register the service with the form element manager in module.config.php.
return [
'form_elements' => [
'factories' => [
'RoleSelect' => 'MyModule\Form\Element\RoleSelectFactory',
],
],
];
There is not need to extend the standard select class as the changes are configuration only. This is best done in a factory class.
namespace MyModule\Form\Element;
use Zend\Form\Element\Select;
class RoleSelectFactory
{
public function __invoke($formElementManager, $name, $rname)
{
$select = new Select('role_id');
$select->setOptions(['label' => 'Role']);
$select->setAttributes(['id' => 'role_id']);
$serviceManager = $formElementManager->getServiceLocator();
$roleService = $serviceManager->get('Admin\Service\RoleService');
$options = [];
foreach($roleService->getAllTheRoles() as $role){
$options[$role->getId()] => $role->getName();
}
$select->setValueOptions($options);
return $select;
}
}
Adding the element within a form can then be updated to use the name of the service we registered.
$this->add([
'name' => 'role_id'
'type' => 'RoleSelect',
]);
One important point to remember is that the form using this element must be created using the $formElementManager->get('FormWithRoleSelect').
Finally found out the simple way to do this, Am really not sure if this is the correct way.
Added the Role service in the User Controller
Code in my userController.php
use Admin\Service\RoleServiceInterface;
class UserController extends AbstractActionController
{
/**
* #var \Admin\Service\UserServiceInterface
*/
protected $userService;
protected $roleService;
protected $userForm;
public function __construct(
UserServiceInterface $userService,
RoleServiceInterface $roleService,
FormInterface $userForm
)
{
$this->userService = $userService;
$this->roleService = $roleService;
$this->userForm = $userForm;
}
public function addAction()
{
$request = $this->getRequest();
$roles = $this->roleService->findAllRoles();
foreach ($roles as $role) {
if($role->getStatus() == 1) {
$allRoles[$role->getId()] = $role->getName();
}
}
$this->userForm->__construct(null, array('roleOptions'=>$allRoles));
}
}
My UserControllerFactory.php
<?php
namespace Admin\Factory;
use Admin\Controller\UserController;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class UserControllerFactory implements FactoryInterface
{
/**
* Create service
*
* #param ServiceLocatorInterface $serviceLocator
*
* #return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$realServiceLocator = $serviceLocator->getServiceLocator();
$userService = $realServiceLocator->get('Admin\Service\UserServiceInterface');
$roleService = $realServiceLocator->get('Admin\Service\RoleServiceInterface');
$userInsertForm = $realServiceLocator->get('FormElementManager')->get('Admin\Form\UserForm');
return new UserController(
$userService,
$roleService,
$userInsertForm
);
}
}
Finally the UserForm.php
<?php
namespace Admin\Form;
use Zend\Form\Form;
use Admin\Model\User;
use Zend\Stdlib\Hydrator\ClassMethods;
use Zend\Form\Element\Select;
class UserForm extends Form
{
public function __construct($name = null, $options = array())
{
$roleOptions = array();
if($options) {
$roleOptions = $options['roleOptions'];
}
parent::__construct($name, $options);
$this->setHydrator(new ClassMethods(false));
$this->setObject(new User());
$this->add(array(
'type' => 'hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'select',
'name' => 'roleId',
'attributes' => array(
'id' => 'roleId',
'options' => $roleOptions
),
'options' => array(
'label' => 'Role',
),
));
}
}
This way using service manager I was successfully able to load the data in my for Select option.
Call getAllRoles() inside the controller then You can pass your custom array as parameter for form when you create form object. In form __construct function you can retrieve that array and set like this
'options' => $roles,

Drupal Field API - Settings List

I'm trying to create a 'link_field' in Drupal through a module, I've got the following code but I'd like to configure the field settings to do the following:
Not require title
Update the number of values to unlimited
I'm struggling to find any information around what setting key/pair values you can pass through for these, anyone able to offer some guidance on these?
<?php
/**
* Implements hook_enable().
*
* Create a field. Fields can be created without any needs to attach them to
* entities.
*/
function youtube_carousel_enable() {
$field = array(
'field_name' => 'ytcarousel_field',
'type' => 'link_field',
);
field_create_field($field);
/**
* Bind field to a entity bundle.
*/
$instance = array(
'field_name' => $field['field_name'],
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video'
);
field_create_instance($instance);
}
/**
* Implements hook_disable().
*
* Remove field from node bundle (content type) and then delete the field.
*/
function youtube_carousel_disable() {
$instance = array(
'field_name' => 'ytcarousel_field',
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video'
);
field_delete_instance($instance);
field_delete_field($instance['field_name']);
print 'Removed ' . $instance['field_name'] . "\n";
}
?>
Cheers
After viewing the HTML source to get key/value pairs I've managed to do something similar to the above with the following code:
<?php
/**
* Implements hook_enable().
*
* Create a field. Fields can be created without any needs to attach them to
* entities.
*/
function youtube_carousel_enable() {
$field = array(
'field_name' => 'ytcarousel_field',
'type' => 'link_field',
'cardinality' => -1
);
field_create_field($field);
/**
* Bind field to a entity bundle.
*/
$instance = array(
'field_name' => $field['field_name'],
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video',
'settings' => array('title' => 'required')
);
field_create_instance($instance);
}
/**
* Implements hook_disable().
*
* Remove field from node bundle (content type) and then delete the field.
*/
function youtube_carousel_disable() {
$instance = array(
'field_name' => 'ytcarousel_field',
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video',
'settings' => array('title' => 'required')
);
field_delete_instance($instance);
field_delete_field($instance['field_name']);
print 'Removed ' . $instance['field_name'] . "\n";
}
?>
The cardinality controls have many instances the value can have, "-1" is unlimited.
'cardinality' => -1
The title attribute is controlled via the instance not the field itself, I believe, and it uses text based values rather than numeric.
'settings' => array('title' => 'required')

Magento edit form fieldset - get value of select dropdown into a label

I am working on an edit screen for my grid row. This is what I have so far for this form:
<?php
class Intellibi_Integration_Block_Adminhtml_Manageasendiapickinglists_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form();
$this->setForm($form);
$fieldset = $form->addFieldset('integration_form', array(
'legend' => Mage::helper('integration')->__('Asendia Pick Information')
));
$fieldset->addField('order_number', 'label', array(
'label' => Mage::helper('integration')->__('Order Number'),
'name' => 'order_number'
));
// snipped
$fieldset->addField('pick_status', 'select', array(
'required' => false,
'class' => 'required-entry',
'label' => Mage::helper('integration')->__('Pick Status'),
'name' => 'pick_status',
'values' => Mage::getSingleton('ibi/asendiapickstatus')->getOptionArray(),
'readonly' => 'readonly'
));
// snipped
return parent::_prepareForm();
}
}
This produces the following output in the admin backend:
What I would like to do is change the pick_status column from a select to a label. When I do this, instead of showing the status value "New" it shows the array index like this:
My option array for asendiapickstatus is defined like this in my model:
class Intellibi_Integration_Model_Asendiapickstatus extends Varien_Object
{
const PICK_STATUS_NEW = 1;
const PICK_STATUS_SENT = 2;
const PICK_STATUS_SHIPPED = 3;
static public function getOptionArray()
{
return array(
self::PICK_STATUS_NEW => Mage::helper('integration')->__('New'),
self::PICK_STATUS_SENT => Mage::helper('integration')->__('Sent'),
self::PICK_STATUS_SHIPPED => Mage::helper('integration')->__('Shipped')
);
}
}
So my question is; on the edit form fieldset builder, how do I show the dropdown field "pick_status" value, rather than the current index it's at? So the output will say "New" instead of "1" as shown above. Will I need a custom renderer?
I've solved it like this (with a custom form rendered element):
Added custom fieldset type
$fieldset->addType('pickstatus', 'Intellibi_Integration_Block_Adminhtml_Manageasendiapickinglists_Edit_Tab_Form_Renderer_Fieldset_Pickstatus');
Used the fieldset like this
$fieldset->addField('pick_status', 'pickstatus', array(
'label' => Mage::helper('integration')->__('Pick Status'),
'name' => 'pick_status',
));
Coded the rendered like this
class Intellibi_Integration_Block_Adminhtml_Manageasendiapickinglists_Edit_Tab_Form_Renderer_Fieldset_Pickstatus extends Varien_Data_Form_Element_Abstract
{
protected $_element;
public function getElementHtml()
{
// Load Pick Status
$pick_status = (int)$this->getValue();
$pick_status_list = Mage::getSingleton('ibi/asendiapickstatus')->getOptionArray();
// Finish
return array_key_exists($pick_status, $pick_status_list) ? $pick_status_list[$pick_status] : 'Unknown';
}
}
And it renders like this

Symfony2 Change checkbox values from 0/1 to 'no'/'yes'

I created a form with one checkbox.
UserSettingsType.php:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('newsletter', 'checkbox', array(
'label' => 'Newsletter erhalten',
'attr' => array(
'class' => 'form-control',
),
'required' => false,
));
}
In the UserSettings.php Entity:
/**
* #ORM\Column(name="newsletter", type="boolean")
*/
protected $newsletter;
In the User.php:
/**
* #ORM\Column(type="integer", nullable=true)
*/
protected $user_settings_id;
/**
* #ORM\OneToOne(targetEntity="UserSettings", cascade={"persist"})
* #ORM\JoinColumn(name="user_settings_id", referencedColumnName="id")
*/
protected $settings;
In the PageController.php i handle the settings action:
public function settingsAction() {
$user = $this->getUser();
if ($user->getSettings() !== null) {
$settings = $user->getSettings();
} else {
$settings = new UserSettings($user);
}
$settings_form = $this->createForm(new UserSettingsType(), $settings);
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$em = $this->getDoctrine()->getManager();
$settings_form->bind($request);
if ($settings_form->isValid()) {
$user->setSettings($settings);
$em->persist($user);
$em->flush();
}
}
return $this->render('MyCompMyAppBundle:Page:settings.html.twig', array(
'settings_form' => $settings_form->createView(),
));
}
I want to change the checkbox values from false (unchecked) / true (checked) to 'no' / 'yes' and change the definition of the newsletter field to: * #ORM\Column(name="newsletter", type="string", columnDefinition="ENUM('yes', 'no')")
It would be nice if there would be 'yes' and 'no' enum values in the database.
Please correct me if i am wrong: There is no way to change this via form element attributes, right?
I heard something about a DataTransformer:. But is there any easier way to realize this?
do you want checkbox or radio button? for checkbox in peresentation use:
$builder->add('newsletter', 'choice', array(
'label' => 'Newsletter erhalten',
'attr' => array(
'class' => 'form-control',
),
'choices' => array(array('yes' => 'yes'), array('no' => 'no')),
'expanded' => true,
'multiple' => true,
'required' => false,
));
Don't use ENUM for this!
In MySQL, use either data type BIT(1) or TINYINT(1) (=same as BOOLEAN). See here: Which MySQL data type to use for storing boolean values
In PostgreSQL, there is a true BOOLEAN type. But no ENUM. So if you're ever thinking about migrating, better get rid of ENUM ;-)

ZF2: Validate collection field based on parent fieldset element

I'm trying to validate a field inside a Collection.
The Collection refers to Company Areas and is tied to a Company Fieldset
The validation needs to check that the Area Name doesn't exists for that Company in the Database yet.
I'm trying to do this using a Callback validator within my collection element 'area_name', my problem is that the collection is aware only of its own context, that means all fields associated to the Area but not aware of the Company context, so i can't filter my validator by its Company parent.
Is there a way to access the parent context of a collection? or should i need to initialize my form passing the Company object to the Collection prior validating?
EDIT: I forgot to mention that i'm using Doctrine2 so i'm not sure if it is possible to use the Db_NoRecordExists Validator bundled with ZF2
This is an old question and you might have fixed this already, but I had a similar problem recently.
You can create a function in your area model/service: validateAreaCompanyRelation(area, company)and in your fieldset use the callback to use it:
AreaService class:
add a method to return true or false based on query limited by 1 row.
in my case it was somthing like this:
public function validateAreaCompanyRelation($company, $area)
{
$result = false;
$count = $this->getRepository()
->createQueryBuilder('q')
->select('q')
->innerJoin('q.company', 'c')
->innerJoin('q.area','b')
->where('b.id = :area and c.company = :company')
->setParameter('area',$area)
->setParameter('company',$area)
->setMaxResults( 1 )
->getQuery()
->getArrayResult();
if(count($count) <>1){
$result=true;
}
return $result;
}
Area Field set:
inject AreaService to the field set (pass it to construct in factory)
class AreaFieldset extends Fieldset implements InputFilterProviderInterface
{
private $areaService;
public function __construct(areaServiceEntityService $areaService)
{
$this->areaService = $areaService;
}
public function init()
{
$this->add(
array(
'name' => 'area',
'filters' => array(),
'validators' => array (
array(
'name' => 'Zend\Validator\Callback',
'options' => array(
'messages' => array(
\Zend\Validator\Callback::INVALID_VALUE => 'Your custom error message',
),
'callback' => array($this,'vlidateUniqueRelation'),
),
),
)
)
);
array(
'name' => 'company',
'filters' => array(),
'validators' => array (
array(
'name' => 'Zend\Validator\Callback',
'options' => array(
'messages' => array(
\Zend\Validator\Callback::INVALID_VALUE => 'Your custom error message',,
),
'callback' => array($this,'vlidateUniqueRelation'),
),
),
)
)
);
}
public function vlidateUniqueRelation($value, $context)
{
// $value = value
// $context['xxxx'] = xxxxx value
// Logic to validate goes here
$context["company"]
$context["area"]
return $this->AreaService->validateAreaCompanyRelation($context["company"], $context["Area"]);
}

Categories