Populate Multi select drop drop down zend 3 - php

Hello everyone i am getting really hard time populating my multi select drop down in my form.
what i have tried so far was adding factory for my form which is like this
class MovieFormFactory
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$entityManager = $container->get('doctrine.entitymanager.orm_default');
$actors = $entityManager->getRepository(Actor::class)->findAll();
$form = new MovieForm();
$form->setActors($data);
return $form;
}
}
my form
Class MovieForm extends Form
{
private $actors = [];
public function setActors($actorsData){
$this->actors = $actors
}
public function __construct()
{
parent::__construct('post-form');
$this->setAttribute('method', 'post');
$this->addElements();
$this->addInputFilter();
$this->add([
'type' => 'select',
'name' => 'actors',
'attributes' => [
'id' => 'actors',
'multiple' => true
],
'options' => [
'label' => 'Actors',
'value_options' => $this->actors,
],
]);
$this->add([
'type' => 'select',
'name' => 'directors',
'attributes' => [
'id' => 'directors',
],
'options' => [
'label' => 'Director',
'value_options' => $this->getOptionForSelect($directors),
],
]);
}
/**
* This method adds elements to form (input fields and submit button).
*/
protected function addElements()
{
// Add "title" field
$this->add([
'type' => 'text',
'name' => 'title',
'attributes' => [
'id' => 'title'
],
'options' => [
'label' => 'Title',
],
]);
// Add "description" field
$this->add([
'type' => 'textarea',
'name' => 'description',
'attributes' => [
'id' => 'description'
],
'options' => [
'label' => 'Description',
],
]);
// Add "tags" field
// $this->add([
// 'type' => 'text',
// 'name' => 'actors',
// 'attributes' => [
// 'id' => 'actors',
// 'multiple' => 'multiple'
// ],
// 'options' => [
// 'label' => 'Actors',
// 'value_options' => $this->getOptionForSelect(),
// ],
// ]);
// Add "status" field
$this->add([
'type' => 'select',
'name' => 'status',
'attributes' => [
'id' => 'status'
],
'options' => [
'label' => 'Status',
'value_options' => [
MovieStatusEnum::STATUS_DRAFT => MovieStatusEnum::STATUS_DRAFT,
MovieStatusEnum::STATUS_PUBLISHED => MovieStatusEnum::STATUS_PUBLISHED,
]
],
]);
// Add the submit button
$this->add([
'type' => 'submit',
'name' => 'submit',
'attributes' => [
'value' => 'Create',
'id' => 'submitbutton',
],
]);
}
/**
* This method creates input filter (used for form filtering/validation).
*/
private function addInputFilter()
{
$inputFilter = new InputFilter();
$this->setInputFilter($inputFilter);
$inputFilter->add([
'name' => 'title',
'required' => true,
'filters' => [
['name' => 'StringTrim'],
['name' => 'StripTags'],
['name' => 'StripNewlines'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 1024
],
],
],
]);
$inputFilter->add([
'name' => 'description',
'required' => true,
'filters' => [
['name' => 'StripTags'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 4096
],
],
],
]);
$inputFilter->add([
'name' => 'actors',
'required' => true,
]);
}
private function getOptionForSelect($data)
{
foreach ($data as $person) {
$selectData[$person->getId()] = $person->getName();
}
return $selectData;
}
}
and this is my registered factory in module.config.php
'form_elements' => [
'factories' => [
Form\MovieForm::class => Form\Factory\MovieFormFactory::class
]
],
but nothing seems to work i am unable to show my actors while creating a movie and unable to show selected actors while editing a movie can some please guide me here i am new to zend.

In the constructor, the line value_options' => $this->actors is wrong because $this->actors is not set yet. In your factory you write :
$form = new MovieForm();
$form->setActors($data);
You must therefore declare the public method setActors() in the class MovieForm which will take care of setting up the options array.
public function setActors($array)
{
$this->get('actors')->setValueOptions($array);
}

Related

Additional attributes in select options

In createForm.php I have code:
$this->add([
'type' => Element\Select::class,
'name' => 'subcategory_id',
'options' =>[
'label' => 'Subcategory',
'empty_option' => 'Select...',
'value_options' => $subcategoriesTable->fetchAllSubcategories(),
],
'attributes' => [
'required' => false,
'class' => 'custom-select',
],
]);
In SubcategoriesTable.php
public function fetchAllSubcategories()
{
$sqlQuery = $this->sql->select()->order('sub_name ASC');
$sqlStmt = $this->sql->prepareStatementForSqlObject($sqlQuery);
$handler = $sqlStmt->execute();
$row = [];
foreach($handler as $tuple){
$row[$tuple['subcategory_id']] = $tuple['sub_name'];
}
return $row;
}
And generated records from my database to my form:
<option value="1">Name1</option>
How I can change my code for making additional attribute like this?
<option value="1" data-chained="parent_name">Name1</option>
parent name value is from another select. Also generated in the same way.
You'll have to make a few changes.
Inside SubcategoriesTable, you'll have to retrieve the parent's name (I used parent_name as key, since we don't know what the exact column's name..):
public function fetchAllSubcategories()
{
$sqlQuery = $this->sql->select()->order('sub_name ASC');
$sqlStmt = $this->sql->prepareStatementForSqlObject($sqlQuery);
$handler = $sqlStmt->execute();
$row = [];
foreach($handler as $tuple){
$row[$tuple['subcategory_id']] = [
'sub_name' => $tuple['sub_name'],
'parent_name' => $tuple['parent_name']
];
}
return $row;
}
Then, in CreateForm:
$valueOptions = [];
foreach($subcategoriesTable->fetchAllSubcategories() as $subcategoryId => $subcategory){
$valueOptions[] = [
'value' => $subcategoryId,
'label' => $subcategory['sub_name'],
'attributes' => [
'data-chained' => $subcategory['parent_name']
]
];
}
$this->add([
'type' => Element\Select::class,
'name' => 'subcategory_id',
'options' =>[
'label' => 'Subcategory',
'empty_option' => 'Select...',
'value_options' => $valueOptions,
],
'attributes' => [
'required' => false,
'class' => 'custom-select',
],
]);
Re-reading your question, I saw that you need this value for another select. I suggest you to add parent's ID instead of parent's name, it would be easier to handle thing.
As exemple:
public function formAction() {
$subcagetoryForm = new Form();
$subcagetoryForm->add([
'type' => Select::class,
'name' => 'subcategory_id',
'options' => [
'label' => 'Subcategory',
'empty_option' => 'Select...',
'value_options' => [
[
'value' => 1,
'label' => 'Name 1',
'attributes' => [
'data-chained' => 'parent 1'
]
],
[
'value' => 2,
'label' => 'Name 2',
'attributes' => [
'data-chained' => 'parent 2'
]
]
],
],
'attributes' => [
'required' => false,
'class' => 'custom-select',
],
]);
return [
'subcagetoryForm' => $subcagetoryForm
];
}
In the view:
<?= $this->formElement($this->subcagetoryForm->get('subcategory_id')); ?>
Result:
[]
However, I'll suggest you to create a custom element to remove all this logic from the form. The custom element will be helpful if you'll need it inside another form. You can take a look at this question

Failed to Insert Data with zend-form

I have a mode named Album as follows:
namespace Album\Model;
// Add the following import statements:
use DomainException;
use Zend\Filter\StringTrim;
use Zend\Filter\StripTags;
use Zend\Filter\ToInt;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Validator\StringLength;
class Album {
public $id;
public $artist;
public $title;
private $inputFilter;
public function exchangeArray(array $data) {
$this->id = !empty($data['_id']) ? $data['_id'] : null;
$this->artist = !empty($data['artist']) ? $data['artist'] : null;
$this->title = !empty($data['title']) ? $data['title'] : null;
}
public function setInputFilter(InputFilterInterface $inputFilter) {
throw new DomainException(sprintf(
'%s does not allow injection of an alternate input filter', __CLASS__
));
}
public function getInputFilter() {
if ($this->inputFilter) {
return $this->inputFilter;
}
$inputFilter = new InputFilter();
$inputFilter->add([
'name' => 'id',
'required' => true,
'filters' => [
['name' => StripTags::class],
['name' => StringTrim::class],
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
],
],
],
]);
$inputFilter->add([
'name' => 'title',
'required' => true,
'filters' => [
['name' => StripTags::class],
['name' => StringTrim::class],
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
],
],
],
]);
$inputFilter->add([
'name' => 'artist',
'required' => true,
'filters' => [
['name' => StripTags::class],
['name' => StringTrim::class],
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
],
],
],
]);
$this->inputFilter = $inputFilter;
return $this->inputFilter;
}
public function getArrayCopy() {
return [
'id' => $this->id,
'artist' => $this->artist,
'title' => $this->title,
];
}
}
And a form named AlbumForm as follows:
namespace Album\Form;
use Zend\Form\Form;
class AlbumForm extends Form
{
public function __construct($name = null)
{
// We will ignore the name provided to the constructor
parent::__construct('album');
$this->add([
'name' => 'id',
'type' => 'hidden',
]);
$this->add([
'name' => 'title',
'type' => 'text',
'options' => [
'label' => 'Title',
],
]);
$this->add([
'name' => 'artist',
'type' => 'text',
'options' => [
'label' => 'Artist',
],
]);
$this->add([
'name' => 'submit',
'type' => 'submit',
'attributes' => [
'value' => 'Go',
'id' => 'submitbutton',
],
]);
}
}
And a controller named AlbumController in which I have addAction as follows:
public function addAction() {
$form = new AlbumForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if (!$request->isPost()) {
return ['form' => $form];
}
$album = new Album();
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if (!$form->isValid()) {
return ['form' => $form];
}
$album->exchangeArray($form->getData());
$this->table->saveAlbum($album);
return $this->redirect()->toRoute('album');
}
The module.config.php file is as follows and I see no problem with routing:
return [
// The following section is new and should be added to your file:
'router' => [
'routes' => [
'album' => [
'type' => Segment::class,
'options' => [
'route' => '/album[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\AlbumController::class,
'action' => 'index',
],
],
],
],
],
'view_manager' => [
'template_path_stack' => [
'album' => __DIR__ . '/../view',
],
],
];
but, I cannot add a new album to the db. Once, I press fill the form and hit 'Add' in the Add form, nothing is added and I remain in the same page. Does anyone know where I have messed up?
You have an error on the Model Album. It could have the following change:
$inputFilter->add([
'name' => 'id',
'required' => true,
'filters' => [
['name' => ToInt::class],
],
]);

Add instantiated validtor to input filter

I'd like to figure out how to add this instantiated file extension validator to the input filter for my flagicon element.
Here is the input filter code:
$inputFilter = new InputFilter();
$this->setInputFilter($inputFilter);
$validator = new \Zend\Validator\File\Extension(array('php'));
$inputFilter->add([
'name' => 'flagicon',
'required' => true,
'filters' => [],
'validators'=>[
[$validator]
]
]);
And Here is my Form Element Code (right from an extended Form object)
$this->add([
'type' => 'file',
'name' => 'flagicon',
'attributes' => [
'id' => 'flagicon',
'class' => 'form-control'
],
'options' => [
'label' => 'Locale Flag Icon',
],
]);
$validator = new \Zend\Validator\File\Extension('jpeg,jpg,png,gif');
$file = new Input('flagicon');
$file->getValidatorChain()->addValidator($validator);
$inputFilter->add($file);
You could also use array notation:
$inputFilter->add([
'name' => 'flagicon',
'required' => true,
'filters' => [],
'validators' => [
[
'name' => 'Extension',
'options' => [
'extension' => 'php',
]
]
]
]);

Laravel backpack select_from_array

I am totally confused with select_from_array field in laravel backpack.
in my controller i am using a select_from_array field where in options i call a function,but when i run the code error is displayed. please help me with this.
Error : FatalErrorException in EventController.php line 106: syntax error, unexpected '$this' (T_VARIABLE)
controller.php
public $crud = array(
"model" => "App\Larapen\Models\Event",
"entity_name" => "event",
"entity_name_plural" => "events",
"route" => "admin/event",
"reorder" => true,
"reorder_label" => "name",
"reorder_max_level" => 2,
"details_row" => true,
// *****
// COLUMNS
// *****
"columns" => [
[
'name' => "id",
'label' => "ID"
],
],
"fields" => [
[
'name' => "event_name",
'label' => "Event name",
'type' => "text",
'placeholder' => "Event Name",
],
[
'name' => "event_topic",
'label' => "Event Topic",
'type' => "text",
'placeholder' => "Event Topic",
],
[
'name' => "event_type_id",
'label' => "Event Type",
'model' => "App\Larapen\Models\EventType",
'entity' => "eventType",
'attribute' => "name",
'type' => "select",
],
[
'name' => "about_event",
'label' => "About event",
'type' => "ckeditor",
'placeholder' => "About the Event",
],
[
'name' => "country_code",
'label' => "Country",
'type' => 'select_from_array',
'options' => $this->countries(),
'allows_null' => false,
],
],
);
public function countries()
{
..................
}
Please help me with this , why this happens? how to solve this issue?
Waiting for a response................
You can not use the pseudo-variable $this out of class method.
http://php.net/manual/en/language.oop5.properties.php
The pseudo-variable $this is available inside any class method when that method is called from within an object context. $this is a reference to the calling object
So if you want to set the attribute of crud's with $this, you can set it in the __construct function
public function __construct()
{
$this->crud['fields'][4] = $this->countries();
}
Or initialize it the __construct function
public $crud;
public function __construct()
{
$this->crud = array(
'model' => 'App\Larapen\Models\Event',
'entity_name' => 'event',
'entity_name_plural' => 'events',
'route' => 'admin/event',
'reorder' => true,
'reorder_label' => 'name',
'reorder_max_level' => 2,
'details_row' => true,
// *****
// COLUMNS
// *****
'columns' => [
[
'name' => 'id',
'label' => 'ID'
],
],
'fields' => [
[
'name' => 'event_name',
'label' => 'Event name',
'type' => 'text',
'placeholder' => 'Event Name',
],
[
'name' => 'event_topic',
'label' => 'Event Topic',
'type' => 'text',
'placeholder' => 'Event Topic',
],
[
'name' => 'event_type_id',
'label' => 'Event Type',
'model' => 'App\Larapen\Models\EventType',
'entity' => 'eventType',
'attribute' => 'name',
'type' => 'select',
],
[
'name' => 'about_event',
'label' => 'About event',
'type' => 'ckeditor',
'placeholder' => 'About the Event',
],
[
'name' => 'country_code',
'label' => 'Country',
'type' => 'select_from_array',
'options' => $this->countries(),
'allows_null' => false,
],
],
);
}

ZF2 form doesn't validate because of input filter

In ZF2, I have a controller whose action works with the form like this
if ($request->isPost()) {
$this->organizationForm->setInputFilter(new OrganizationFilter());
$this->organizationForm->setData($request->getPost());
if ($this->organizationForm->isValid()) {
// further logic to process
The InputFilter OrganizationFilter is this
class OrganizationFilter extends InputFilter
{
public function __construct()
{
$this->add([
'name' => 'id',
'filters' => [
['name' => 'Int'],
]
]);
$this->add([
'name' => 'name',
'required' => true,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 3,
'max' => 160
]
]
]
]);
}
}
If I comment the line $this->organizationForm->setInputFilter(new OrganizationFilter()), the form gets validated, but with this line, it doesn't work.
How to get it validated?
I couldn't figure out why my code didn't work, but I solved it in another way. For the form with inputs to be validated, I implemented InputFilterProviderInterface. Then in the form, getInputFilterSpecification()
public function getInputFilterSpecification()
{
return [
'name' => [
'required' => true,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 3,
'max' => 160
]
]
]
],
// other inputs to filter
];
}
defines all the inputs to be validated. With this implementation, I don't have to set the filter explicitly in the controller, just call $this->form->isValid() and magic happens. :-)

Categories