Why the view block under the search field was not rendered? - drupal

I created a block based on the view with machine name search_entity_product_block:
Then I created a custom form with method someMethod which should render a block of the view below the search field:
class SearchFieldForm extends FormBase {
public function getFormId() {
return 'entity_product_admin_search_field';
}
public function someMethod($args) {
$view = [
'#type' => 'view',
'#name' => 'search_entity_product',
'#display_id' => 'search_entity_product_block',
'#arguments' => $args,
'#embed' => TRUE,
];
return $view;
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['search_field'] = [
'#type' => 'textfield',
'#title' => $this->t('Search Product'),
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Save'),
];
return $form;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$args = $form_state->getValue('search_field');
$this->someMethod($args);
}
}
But the block didn't render.

Related

Sonata ModelAutocompleteType result affected by getFilterParameters

I have this form field of a type ModelAutocompleteType that is supposed to show the result filtered by the "search" datagrid field of related admin:
class OperationAdmin extends AbstractAdmin
{
// ...
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('business', ModelAutocompleteType::class, [
'label' => 'Business',
'property' => 'search'
]);
}
// ...
}
In this related "business" admin I have few filters defined as:
class BusinessAdmin extends AbstractAdmin
{
// ...
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('search', CallbackFilter::class, [
'label' => 'Search',
'show_filter' => true,
'advanced_filter' => false,
'callback' => function($qb, $alias, $field, $value) {
if (!$value['value']) return;
// ...
return true;
}
])
->add('state', ChoiceFilter::class, [
'label' => 'State',
'show_filter' => true,
'advanced_filter' => false,
'field_options' => ['choices' => Business::STATES],
'field_type' => 'choice'
]);
}
// ...
}
Now, if I set the default "state" datagrid field value using getFilterParameters to filter business list by state on initial page load:
public function getFilterParameters()
{
$this->datagridValues = array_merge([
'state' => ['type' => '', 'value' => 'active']
], $this->datagridValues);
return parent::getFilterParameters();
}
The related ModelAutocompleteType form field's result will also be filtered by "state" field even tho it's property is set to search.
How do I apply default filter values JUST to list view and nothing else? And why ModelAutocompleteType result depends on other datagrid fields even tho property is set to one?
In the end I left getFilterParameters method in to filter list by default, which is what I wanted:
public function getFilterParameters()
{
$this->datagridValues = array_merge([
'state' => ['type' => '', 'value' => 'active']
], $this->datagridValues);
return parent::getFilterParameters();
}
Unfortunatelly, that was also affecting ModelAutocompleteFilter and ModelAutocompleteType results, filtering them by 'active' state too, which I did not want.
To solve that I had to pass a callback property to ModelAutocompleteType field, to reset datagrid state value:
class OperationAdmin extends AbstractAdmin
{
// ...
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('business', ModelAutocompleteType::class, [
'label' => 'Business',
'property' => 'search',
'callback' => [$this, 'filterAllBusinessesCallback']
]);
}
public function filterAllBusinessesCallback(AdminInterface $admin, $property, $value)
{
$datagrid = $admin->getDatagrid();
$datagrid->setValue($property, null, $value);
$datagrid->setValue('state', null, null);
}
// ...
}

How to apply InputFilter validators to fieldset elements in ZF3

I had a form that had two fields. An InputFilter with validators was applied to it. It was working fine. Then I moved the fields to a fieldset and added the fieldset to the form. Now the assignment validators to the fields is not present. The validator objects isValid method is not triggered at all. So how to apply the InputFilter validators to fields in a fieldset? Here you are the classes:
Text class Validator
namespace Application\Validator;
use Zend\Validator\StringLength;
use Zend\Validator\ValidatorInterface;
class Text implements ValidatorInterface
{
protected $stringLength;
protected $messages = [];
public function __construct()
{
$this->stringLengthValidator = new StringLength();
}
public function isValid($value, $context = null)
{
if (empty($context['url'])) {
if (empty($value)) return false;
$this->stringLengthValidator->setMin(3);
$this->stringLengthValidator->setMax(5000);
if ($this->stringLengthValidator->isValid($value)) {
return true;
}
$this->messages = $this->stringLengthValidator->getMessages();
return false;
}
if (!empty($value)) return false;
return true;
}
public function getMessages()
{
return $this->messages;
}
}
Test class InputFilter
namespace Application\Filter;
use Application\Fieldset\Test as Fieldset;
use Application\Validator\Text;
use Application\Validator\Url;
use Zend\InputFilter\InputFilter;
class Test extends InputFilter
{
public function init()
{
$this->add([
'name' => Fieldset::TEXT,
'required' => false,
'allow_empty' => true,
'continue_if_empty' => true,
'validators' => [
['name' => Text::class],
],
]);
$this->add([
'name' => Fieldset::URL,
'required' => false,
'allow_empty' => true,
'continue_if_empty' => true,
'validators' => [
['name' => Url::class],
],
]);
}
}
Test class Fieldset
namespace Application\Fieldset;
use Zend\Form\Fieldset;
class Test extends Fieldset
{
const TEXT = 'text';
const URL = 'url';
public function init()
{
$this->add([
'name' => self::TEXT,
'type' => 'textarea',
'attributes' => [
'id' => 'text',
'class' => 'form-control',
'placeholder' => 'Type text here',
'rows' => '6',
],
'options' => [
'label' => self::TEXT,
],
]);
$this->add([
'name' => self::URL,
'type' => 'text',
'attributes' => [
'id' => 'url',
'class' => 'form-control',
'placeholder' => 'Type url here',
],
'options' => [
'label' => self::URL,
],
]);
}
}
Test class Form
namespace Application\Form;
use Application\Fieldset\Test as TestFieldset;
use Zend\Form\Form;
class Test extends Form
{
public function init()
{
$this->add([
'name' => 'test',
'type' => TestFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
$this->add([
'name' => 'submit',
'attributes' => [
'type' => 'submit',
'value' => 'Send',
],
]);
}
}
TestController class
namespace Application\Controller;
use Application\Form\Test as Form;
use Zend\Debug\Debug;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class TestController extends AbstractActionController
{
private $form;
public function __construct(Form $form)
{
$this->form = $form;
}
public function indexAction()
{
if ($this->getRequest()->isPost()) {
$this->form->setData($this->getRequest()->getPost());
Debug::dump($this->getRequest()->getPost());
if ($this->form->isValid()) {
Debug::dump($this->form->getData());
die();
}
}
return new ViewModel(['form' => $this->form]);
}
}
TestControllerFactory class
namespace Application\Factory;
use Application\Controller\TestController;
use Application\Form\Test;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class TestControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$form = $container->get('FormElementManager')->get(Test::class);
return new TestController($form);
}
}
Test class
namespace Application\Factory;
use Application\Filter\Test as Filter;
use Application\Entity\Form as Entity;
use Application\Form\Test as Form;
use Interop\Container\ContainerInterface;
use Zend\Hydrator\ClassMethods;
use Zend\ServiceManager\Factory\FactoryInterface;
class Test implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return (new Form())
->setHydrator($container
->get('HydratorManager')
->get(ClassMethods::class))
->setObject(new Entity())
->setInputFilter($container->get('InputFilterManager')->get(Filter::class));
}
}
Test Fieldset
namespace Application\Factory;
use Application\Entity\Fieldset as Entity;
use Application\Fieldset\Test as Fieldset;
use Interop\Container\ContainerInterface;
use Zend\Hydrator\ClassMethods;
use Zend\ServiceManager\Factory\FactoryInterface;
class TestFieldset implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return (new Fieldset())
->setHydrator($container->get('HydratorManager')->get(ClassMethods::class))
->setObject(new Entity());
}
}
UPDATE
I updated the fieldset class accordingly to #Nukeface advise by adding setInputFilter(). But it did not worked. It even had not executed InpuFilter class init method. Perhaps I did in wrong:
<?php
namespace Application\Fieldset;
use Application\Filter\Test as Filter;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterAwareTrait;
class Test extends Fieldset
{
use InputFilterAwareTrait;
const TEXT = 'text';
const URL = 'url';
public function init()
{
$this->add([
'name' => self::TEXT,
'type' => 'textarea',
'attributes' => [
'id' => 'text',
'class' => 'form-control',
'placeholder' => 'Type text here',
'rows' => '6',
],
'options' => [
'label' => self::TEXT,
],
]);
$this->add([
'name' => self::URL,
'type' => 'text',
'attributes' => [
'id' => 'url',
'class' => 'form-control',
'placeholder' => 'Type url here',
],
'options' => [
'label' => self::URL,
],
]);
$this->setInputFilter(new Filter());
}
}
Tried an answer before and ran out of chars (30k limit), so created a repo instead. The repo contains abstraction of the answer below, which is a working example.
Your question shows you having the right idea, just not yet the implementation. It also contains a few mistakes, such as setting a FQCN for a Fieldset name. Hopefully the below can have you up and running.
As a use case, we'll have a basic Address form. Relationships for Country, Timezones and other things I'll leave out of the scope. For more in depth and nesting of Fieldsets (also with Collections) I'll refer you to my repo.
General setup
First create the basic setup. Create the Entity and configuration.
Basic Entity
namespace Demo\Entity;
class Address
{
protected $id; // int - primary key - unique - auto increment
protected $street; // string - max length 255 - not null
protected $number; // int - max length 11 - not null
protected $city; // string - max length 255 - null
// getters/setters/annotation/et cetera
}
To handle this in a generic and re-usable way, we're going to need:
AddressForm (general container)
AddressFormFieldset (form needs to be validated)
AddressFieldset (contains the entity inputs)
AddressFieldsetInputFilter (must validate the data entered)
AddressController (to handle CRUD actions)
Factory classes for all of the above
a form partial
Configuration
To tie these together in Zend Framework, these need to be registered in the config. With clear naming, you can already add these. If you're using something like PhpStorm as your IDE, you might want to leave this till last, as the use statements can be generated for you.
As this is an explanation, I'm showing you now. Add this to your module's config:
// use statements here
return [
'controllers' => [
'factories' => [
AddressController::class => AddressControllerFactory::class,
],
],
'form_elements' => [ // <-- note: both Form and Fieldset classes count as Form elements
'factories' => [
AddressForm::class => AddressFormFactory::class,
AddressFieldset::class => AddressFieldsetFactory::class,
],
],
'input_filters' => [ // <-- note: input filter classes only!
'factories' => [
AddressFormInputFilter::class => AddressFormInputFilterFactory::class,
AddressFieldsetInputFilter::class => AddressFieldsetInputFilterFactory::class,
],
],
'view_manager' => [
'template_map' => [
'addressFormPartial' => __DIR__ . '/../view/partials/address-form.phtml',
],
];
Fieldset
First we create the Fieldset (and Factory) class. This is because this contains the actual object we're going to handle.
AddressFieldset
// other use statements for Elements
use Zend\Form\Fieldset;
class AddressFieldset extends Fieldset
{
public function init()
{
parent::init(); // called due to inheritance
$this->add([
'name' => 'id',
'type' => Hidden::class,
]);
$this->add([
'name' => 'street',
'required' => true,
'type' => Text::class,
'options' => [
'label' => 'Name',
],
'attributes' => [
'minlength' => 1,
'maxlength' => 255,
],
]);
$this->add([
'name' => 'number',
'required' => true,
'type' => Number::class,
'options' => [
'label' => 'Number',
],
'attributes' => [
'step' => 1,
'min' => 0,
],
]);
$this->add([
'name' => 'city',
'required' => false,
'type' => Text::class,
'options' => [
'label' => 'Name',
],
'attributes' => [
'minlength' => 1,
'maxlength' => 255,
],
]);
}
}
AddressFieldsetFactory
// other use statements
use Zend\ServiceManager\Factory\FactoryInterface;
class AddressFieldsetFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$this->setEntityManager($container->get(EntityManager::class));
/** #var AddressFieldset $fieldset */
$fieldset = new AddressFieldset($this->getEntityManager(), 'address');
$fieldset->setHydrator(
new DoctrineObject($this->getEntityManager())
);
$fieldset->setObject(new Address());
return $fieldset;
}
}
InputFilter
Above we created the Fieldset. That allows for the generation of the Fieldset for in a Form. At the same time, Zend Framework also has defaults already set per type of input (e.g. 'type' => Text::class). However, if we want to validate it to our own, more strict, standards, we need to override the defaults. For this we need an InputFilter class.
AddressFieldsetInputFilter
// other use statements
use Zend\InputFilter\InputFilter;
class AddressFieldsetInputFilter extends InputFilter
{
public function init()
{
parent::init(); // called due to inheritance
$this->add([
'name' => 'id',
'required' => true,
'filters' => [
['name' => ToInt::class],
],
'validators' => [
['name' => IsInt::class],
],
]);
$this->add([
'name' => 'street',
'required' => true,
'filters' => [
['name' => StringTrim::class], // remove whitespace before & after string
['name' => StripTags::class], // remove unwanted tags
[ // if received is empty string, set to 'null'
'name' => ToNull::class,
'options' => [
'type' => ToNull::TYPE_STRING, // also supports other types
],
],
],
'validators' => [
[
'name' => StringLength::class, // set min/max string length
'options' => [
'min' => 1,
'max' => 255,
],
],
],
]);
$this->add([
'name' => 'number',
'required' => true,
'filters' => [
['name' => ToInt::class], // received from HTML form always string, have it cast to integer
[
'name' => ToNull::class, // if received is empty string, set to 'null'
'options' => [
'type' => ToNull::TYPE_INTEGER,
],
],
],
'validators' => [
['name' => IsInt::class], // check if actually integer
],
]);
$this->add([
'name' => 'city',
'required' => false, // <-- not required
'filters' => [
['name' => StringTrim::class], // remove whitespace before & after string
['name' => StripTags::class], // remove unwanted tags
[ // if received is empty string, set to 'null'
'name' => ToNull::class,
'options' => [
'type' => ToNull::TYPE_STRING, // also supports other types
],
],
],
'validators' => [
[
'name' => StringLength::class, // set min/max string length
'options' => [
'min' => 1,
'max' => 255,
],
],
],
]);
}
}
AddressFieldsetInputFilterFactory
// other use statements
use Zend\ServiceManager\Factory\FactoryInterface;
class AddressFieldsetInputFilterFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// Nothing else required in this example. So it's as plain as can be.
return new AddressFieldsetInputFilter();
}
}
Form & Validation
So. Above we created the Fieldset, it's InputFilter and 2 required Factory classes. This already allows us to do a great deal, such as:
use the InputFilter in stand-alone setting to dynamically validate an object
re-use Fieldset + InputFilter combination in other Fieldset and InputFilter classes for nesting
Form
use Zend\Form\Form;
use Zend\InputFilter\InputFilterAwareInterface;
// other use statements
class AddressForm extends Form implements InputFilterAwareInterface
{
public function init()
{
//Call parent initializer. Check in parent what it does.
parent::init();
$this->add([
'type' => Csrf::class,
'name' => 'csrf',
'options' => [
'csrf_options' => [
'timeout' => 86400, // day
],
],
]);
$this->add([
'name' => 'address',
'type' => AddressFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
$this->add([
'name' => 'submit',
'type' => Submit::class,
'attributes' => [
'value' => 'Save',
],
]);
}
}
Form Factory
use Zend\ServiceManager\Factory\FactoryInterface;
// other use statements
class AddressFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** #var AbstractForm $form */
$form = new AddressForm('address', $this->options);
$form->setInputFilter(
$container->get('InputFilterManager')->get(ContactFormInputFilter::class);
);
return $form;
}
}
Making it all come together
I'll show just the AddressController#addAction
AddressController
use Zend\Mvc\Controller\AbstractActionController;
// other use statements
class AddressController extends AbstractActionController
{
protected $addressForm; // + getter/setter
protected $entityManager; // + getter/setter
public function __construct(
EntityManager $entityManager,
AddressForm $form
) {
$this->entityManager = $entityManager;
$this->addressForm = $form;
}
// Add your own: index, view, edit and delete functions
public function addAction () {
/** #var AddressForm $form */
$form = $this->getAddressForm();
/** #var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$entity = $form->getObject();
$this->getEntityManager()->persist($entity);
try {
$this->getEntityManager()->flush();
} catch (\Exception $e) {
$this->flashMessenger()->addErrorMessage($message);
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
$this->flashMessenger()->addSuccessMessage(
'Successfully created object.'
);
return $this->redirect()->route($route, ['param' => 'routeParamValue']);
}
$this->flashMessenger()->addWarningMessage(
'Your form contains errors. Please correct them and try again.'
);
}
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
}
AddressControllerFactory
class AddressControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** #var AddressController $controller */
$controller = new AddressController(
$container->get(EntityManager::class),
$container->get('FormElementManager')->get(AddressForm::class);
);
return $controller;
}
}
Display in addressFormPartial
$this->headTitle('Add address');
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formRow($form->get('csrf'));
echo $this->formRow($form->get('address')->get('id'));
echo $this->formRow($form->get('address')->get('street'));
echo $this->formRow($form->get('address')->get('number'));
echo $this->formRow($form->get('address')->get('city'));
echo $this->formRow($form->get('submit'));
echo $this->form()->closeTag($form);
To use this partial, say in a add.phtml view, use:
<?= $this->partial('addressFormPartial', ['form' => $form]) ?>
This bit of code will work with the demonstrated addAction in the Controller code above.
Hope you found this helpful ;-) If you have any questions left, don't hesitate to ask.
Just use the InputFilterProviderInterface class to your fieldset. This implements the getInputFilterSpecification method to your fieldset, which executes the input filters mentioned in this method.
class MyFieldset extends Fieldset implements InputFilterProviderInterface
{
public function init()
{
$this->add([
'name' => 'textfield',
'type' => Text::class,
'attributes' => [
...
],
'options' => [
...
]
]);
}
public function getInputFilterSpecification()
{
return [
'textfield' => [
'required' => true,
'filters' => [
...
],
'validators' => [
[
'name' => YourTextValidator::class,
'options' => [
...
],
],
],
],
];
}
}
AS long as you add this fieldset in your form the bound filters and validators will be executed on the isValid method call of your form.

Render form in a Twig Template in drupal8

Im curently using drupal 8 and I have created form using form api,
The below code under Module directory
// module/src/Form/ContributeForm
class ContributeForm extends FormBase {
public function getFormId() {
return 'amazing_forms_contribute_form';
}
public function buildForm(array $form, FormStateInterface $form_state)
{
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#required' => TRUE,
);
$form['video'] = array(
'#type' => 'textfield',
'#title' => t('Youtube video'),
);
$form['video'] = array(
'#type' => 'textfield',
'#title' => t('Youtube video'),
);
$form['develop'] = array(
'#type' => 'checkbox',
'#title' => t('I would like to be involved in developing this
material'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
}
public function submitForm(array &$form, FormStateInterface $form_state) {
}
}
Now I need to render above vairables in twig template like below
//themes/page.html.twig
<body>
{{form.title}}
{{form.video}}
{{form.video}}
</body>
the twig will be under theme folder.Is it possible to get variable in page.html.twig file??
The best way to render and custom your form via Twig, you'd use $form['#theme'] value in your form. Example below:
module_name/scr/Form/your_form.php
public function buildForm(array $form, FormStateInterface $form_state){
.....
.....
$form['#theme'] = 'your_form_theme';
return $form;
}
module_name/form.module
function form_theme() {
$themes['your_form_theme'] = ['render element' => 'form'];
return $themes;
}
What is left is creating your custom twig and insert you form fields.
module_name/templates/your-form-theme.html.twig
<body>
{{form.field_1}}
{{form.field_2}}
{{form.field_3}}
</body>
Hope it helps you!
You can create a page by using the controller. From that, you can get the form elements.
Create a module_nameController.php file inside src/Controller folder. In that file create a class that should be extended to Controllerbase. In that file, by using form builder function you can get the form elements.

configureRoutes() in admin class is not compatible with Sonata\AdminBundle\Admin\Admin::configureRoutes()

Hi I'm trying to 'Create a Custom Admin Action' for sonata admin bundle. But I'm facing this issue,
Runtime Notice: Declaration of
AdminBundle\Admin\VideoAdmin::configureRoutes() should be compatible
with
Sonata\AdminBundle\Admin\Admin::configureRoutes(Sonata\AdminBundle\Route\RouteCollection
$collection) in C:\wamp\www\videocenter\app/config. (which is being
imported from "C:\wamp\www\videocenter\app/config\routing.yml").
This is my configureRoutes() function,
protected function configureRoutes(RouteCollection $collection) {
$collection->add('clone', $this->getRouterIdParameter() . '/clone');
}
This is my complete admin class,
namespace AdminBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use AdminBundle\Entity\Video;
use Doctrine\ORM\Query\ResultSetMapping;
class VideoAdmin extends Admin {
protected function configureFormFields(FormMapper $formMapper) {
$formMapper->add('name', 'text');
$formMapper->add('category', 'sonata_type_model', array(
'class' => 'AdminBundle\Entity\VideoCategory',
'property' => 'name',
));
$formMapper->add('thumbUrl', 'text');
$formMapper->add('url', 'text');
// $formMapper->add('videoKey', 'text');
$formMapper->add('isPublic', 'checkbox', array(
'label' => 'Show public',
'required' => false,
));
$formMapper->add('isEnabled', 'checkbox', array(
'label' => 'Enable',
'required' => false,
));
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper) {
$datagridMapper
->add('name')
->add('category', null, array(), 'entity', array(
'class' => 'AdminBundle\Entity\VideoCategory',
'property' => 'name'))
->add('videoKey');
}
protected function configureListFields(ListMapper $listMapper) {
$listMapper
->addIdentifier('name')
->add('category.name')
->add('url')
->add('videoKey')
->add('isPublic')
->add('isEnabled')
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
'delete' => array(),
'clone' => array(
'template' => 'AdminBundle:CRUD:list__action_clone.html.twig'
),
)
))
;
}
public function postPersist($object) {
global $kernel;
if ('AppCache' == get_class($kernel)) {
$kernel = $kernel->getKernel();
}
$em = $kernel->getContainer()->get('doctrine.orm.entity_manager');
$query = "select a.random_num from (SELECT FLOOR(RAND() * 99999) AS random_num) a WHERE A.RANDOM_NUM NOT IN (SELECT COALESCE(B.VIDEO_KEY,0) FROM VIDEO B)";
$stmt = $em->getConnection()->prepare($query);
$stmt->execute();
$randum = $stmt->fetchAll();
$video = $em->getRepository('AdminBundle:Video')->find($object->getId());
if ($video) {
$video->setVideoKey($randum[0]['random_num']);
$em->flush();
}
}
public function toString($object) {
return $object instanceof Video ? $object->getName() : 'Video'; // shown in the breadcrumb on the create view
}
public function getBatchActions() {
// retrieve the default batch actions (currently only delete)
$actions = parent::getBatchActions();
if (
$this->hasRoute('edit') && $this->isGranted('EDIT') &&
$this->hasRoute('delete') && $this->isGranted('DELETE')
) {
$actions['merge'] = array(
'label' => 'action_merge',
'translation_domain' => 'SonataAdminBundle',
'ask_confirmation' => true
);
}
return $actions;
}
protected function configureRoutes(RouteCollection $collection) {
$collection->add('clone', $this->getRouterIdParameter() . '/clone');
}
}
Did you import?
use Sonata\AdminBundle\Route\RouteCollection;
I doesn't see that in yours VideoAdmin class

upload a file in a drupal 8 contributed module

I am trying to create my first drupal 8 module. in this module I have to create a new form and provide user a file uploading capability in this form. here is my form controller:
class Make2d extends FormBase {
/**
* {#inheritdoc}
*/
public function getFormId() {
return 'make2d_form';
}
/**
* {#inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
if (\Drupal::currentUser()->isAnonymous()) {
return new RedirectResponse(\Drupal::url('user.page'));
}
$form['sheet_size'] = array(
'#type' => 'radios',
'#title' => t('Sheet Size'),
'#options' => array(t('10 X 10(2.99$)'), t('17 X 17(4.99$)'), t('28 X 28(5.99$)')),
);
$form['uploaded_file'] = array(
'#type' => 'file',
'#title' => t('Upload your file'),
'#required' => true
);
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Save to Cart'),
'#button_type' => 'primary',
);
return $form;
}
/**
* {#inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
echo '<pre>';
print_r($form_state->getvalues());
echo '</pre>';
}
/**
* {#inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
print_r($form_state['values']);
}
}
this is the result when I go to my form's page:
image of my form
then I choose a file from my computer and submit the form. but when I print_r my $form_state->getvalues() array the result is sth like this:
Array
(
[sheet_size] => 0
[uploaded_file] =>
[submit] => Drupal\Core\StringTranslation\TranslatableMarkup Object
...
you can see that [uploaded_file] is empty. and there is an error on top of the form about uploading a file. what is wrong with the form controller and file uploading.
thanks.
at last! I find it. we should use '#type' = 'managed_file' so that we let drupal to manage uploaded file. in the case we use '#type' = 'file' we must transfer file ourselves by file_save_upload().

Resources