i want to render my form in a twig template that overrides html.html.twig
the twig template is named html--resume--myform.html.twig
inside my form class i have this code
public function buildForm(array $form,FormStateInterface $form_state)
{
$form['#theme'] = ['html__resume__myform'];
$form['candidate_name'] = array(
'#type' => 'textfield',
'#title' => t('Candidate Name:'),
'#required' => TRUE,
);
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Save2'),
'#button_type' => 'primary',
);
return $form
}
and inside my resume.module file i have this custom template
function resume_theme() {
return ['html__resume__myform' => ['render element' => 'form']];
}
but my form is not rendered in html--resume--myform.html.twig
or my $form variable is not passed to html--resume--myform.html.twig
html--resume--myform.html.twig is inside templates folder
Related
i'm trying to show categories in search.twig using events for this i have create a module file to add event.
i am assuming after common/search controller is called the event will add categories to existing data variable and will send categories along all data from common/search controller. i have copied the code below
admin/controller/extention/module/cc_add_search_categories.php
public function install(){
$this->load->model('setting/event');
$this->model_setting_event->addEvent('ccaddsearchcategorise', 'catalog/controller/common/search/after', 'extension/module/cc_add_search_categories/addCategoriesToSearch');
}
public function uninstall(){
$this->load->model('setting/event');
$this->model_setting_event->deleteEventByCode('ccaddsearchcategorise');
}
and in
catalog/controller/extention/module/cc_add_search_categories.php
public function addCategoriesToSearch(&$route, &$data, &$output){
$this->load->model('catalog/category');
$this->load->language('extention/module/cc_add_search_category');
$data['categories'] = array('data');
$categories_1 = $this->model_catalog_category->getCategories(0);
foreach ($categories_1 as $category_1) {
$level_2_data = array();
$categories_2 = $this->model_catalog_category->getCategories($category_1['category_id']);
foreach ($categories_2 as $category_2) {
$level_3_data = array();
$categories_3 = $this->model_catalog_category->getCategories($category_2['category_id']);
foreach ($categories_3 as $category_3) {
$level_3_data[] = array(
'category_id' => $category_3['category_id'],
'name' => $category_3['name'],
);
}
$level_2_data[] = array(
'category_id' => $category_2['category_id'],
'name' => $category_2['name'],
'children' => $level_3_data
);
}
$data['categories'][] = array(
'category_id' => $category_1['category_id'],
'name' => $category_1['name'],
'children' => $level_2_data
);
}
}
I'm trying to create a custom module with configuration for a block that will allow a block to have custom fields. I'm having problems allowing the upload of an image and then rendering this in the block on the site.
Currently this is what my block file looks like;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides a 'hello' block.
*
* #Block(
* id = "hello_block",
* admin_label = #Translation("Hello"),
* category = #Translation("Hello world block")
* )
*/
class HelloBlock extends BlockBase
{
/**
* {#inheritdoc}
*/
public function blockForm($form, FormStateInterface $formState)
{
$form['heading'] = array(
'#type' => 'textfield',
'#title' => t('Heading'),
'#description' => t('Enter the main heading'),
'#default_value' => 'Main heading'
);
$form['sub_heading'] = array(
'#type' => 'textfield',
'#title' => t('Sub heading'),
'#description' => t('Enter the sub heading'),
'#default_value' => 'Sub heading'
);
$form['body'] = array(
'#type' => 'text_format',
'#title' => t('Body'),
'#description' => t('Main body'),
'#format' => 'full_html',
'#rows' => 50,
'#default_value' => ''
);
$form['image'] = array(
'#type' => 'managed_file',
'#upload_location' => 'public://upload/hello',
'#title' => t('Image'),
'#upload_validators' => [
'file_validate_extensions' => ['jpg', 'jpeg', 'png', 'gif']
],
'#default_value' => isset($this->configuration['image']) ? $this->configuration['image'] : '',
'#description' => t('The image to display'),
'#required' => true
);
return $form;
}
/**
* {#inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $formState)
{
$this->configuration['heading'] = $formState->getValue('heading');
$this->configuration['sub_heading'] = $formState->getValue('sub_heading');
$this->configuration['body'] = $formState->getValue('body');
$this->configuration['image'] = $formState->getValue('image');
}
/**
* {#inheritdoc}
*/
public function build()
{
$markup = '<h1>'.$this->configuration['heading'].'</h1>';
$markup .= '<h2>'.$this->configuration['sub_heading'].'</h2>';
$markup .= '<img src="'.$this->configuration['image']['value'].'">';
$markup .= '<div>' . $this->configuration['body'] . '</div>';
return array(
'#type' => 'markup',
'#markup' => $markup,
);
}
}
Can anyone provide some pointers as to why the image isn't appearing? I'm assuming I'm missing something.
The text saved in the body (text_format) also appears in the block on the website as 'array', if anyone can help with that too it would be good, other wise I'll raise another question.
When you save that form, the value from the image field is the File ID.
Therefore, you can get the file object and the path by using:
$image = \Drupal\file\Entity\File::load($fid);
$path = file_create_url($image->getFileUri());
Then you would output the image using that path in your markup variable. There's probably a more semantic way to output the formatted image in a 'Drupal-ish' form, but this will get you started.
Oh, and the body field, use
$form_state->getValue('body')['value'];
in your markup.
BTW, I love using Devel and the ksm() function!
I have done bunch of projects using ZF2 and Doctrine2. I build my form with as it follows: Create Form class extending Form, then create Fieldsets and set it as a base fieldset, then in the fieldset I add my fields. Within module.php I create factories in formElementConfig for my forms. It was working allways this way until now. I created a new project and suddenly I encounter a problem which I cant find what is going on. This is my code
//module.php
public function getFormElementConfig()
{
return array(
'factories' => array(
'OfferForm' => function($sm) {
$locator = $sm->getServiceLocator();
$form = new \Application\Form\OfferForm();
$form->setServiceLocator($locator);
return $form;
},
)
);
}
//Form
class OfferForm extends Form implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function init()
{
$this->setAttributes(array(
'id' => 'offer',
'method' => 'post',
'class' => 'custom',
'enctype' => 'multipart/form-data'
));
$this->setAttribute('method', 'post')
->setHydrator(new ClassMethodsHydrator(false))
->setInputFilter(new InputFilter());
$this->add(array(
'name' => 'offer',
'type' => 'Application\Form\Fieldset\OfferFieldset',
'options' => array(
'use_as_base_fieldset' => true
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf'
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'id' => 'submit',
'type' => 'submit',
'value' => $this->getServiceLocator()->getServiceLocator()->get('translator')->translate('Submit offer'),
'class' => 'btn btn-info'
)
));
}
....
//Fieldset
class OfferFieldset extends Fieldset implements InputFilterProviderInterface, ServiceLocatorAwareInterface
{
public function init()
{
$this->setHydrator(new ClassMethodsHydrator(false))
->setObject(new Offer());
$this->add(array(
'name' => 'title',
'type' => 'Zend\Form\Element\Text',
'attributes' => array(
'required' => 'required',
'class' => 'form-control',
)
));
....other fileds
}
/**
* #return array
*/
public function getInputFilterSpecification()
{
....
}
}
//Controller
$em = $this->getObjectManager();
$offer = new Offer();
$form = $this->getServiceLocator()->get('FormElementManager')->get('OfferForm');
$form->setHydrator(new DoctrineHydrator($em, 'Application\Entity\Offer'))->bind($offer);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
var_dump('ok');
}
}
$form->prepare();
return new ViewModel(array(
'form' => $form,
));
This way of doing things is allways working for me until now. If I try to get form element in the Veiw with $this->form->get('offer')->get('title') it says there is no field with name 'title'
One thing that i noticed is when form is called in the controller ($form = $this->getServiceLocator()->get('FormElementManager')->get('OfferForm');) the fieldset method init() where all my fields are set is not invoked.
I tried to dump data there and to die() the application but it did not get in to the method at all.
I can provide more code but I think this is all about building the form
You also need to add your fieldset to the formelementmanager configuration. The manager's initializer will call your fieldset init() method.
I am trying to make custom page template using these hooks in Drupal 7 but it shows blank page when i open in browser. Here is my code
/*
Implements hook_menu();
*/
function story_menu ()
{
$items['story/filters'] = array(
'title' => 'Search For stories',
'page callback' => 'story_filter_page',
'access arguments' => array('access content'),
);
return $items;
}
// Implements Page Callback
function story_filter_page ()
{
return theme('story_search_filter_page', array('title' => 'Testing'));
}
/*
Implements hook_theme();
*/
function story_theme($existing, $type, $theme, $path)
{
return array(
'story_search_filter_page' => array(
'variables' => array('title' => NULL),
'template' => 'custom-page',
),
);
}
I have created the template file : custom-page.tpl.php in my module directory.
I have figured it out why page is showing blank. basically story is my content type to so in my theme there is a tpl file name : page--story.tpl.php and that file was empty .. so that is why my pages showing me blank screen.
I want to know how I can modify the error message on my ContactType.
It's possible directly in the Type ?
My current code:
class ContactType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$collectionConstraint = new Collection(array(
'name' => array(
new NotBlank(array('message' => 'My custon message.')),
new Length(array('min' => 2), array('message' => 'My custon message.'))
),
'email' => array(
new NotBlank(array('message' => 'My custon message.')),
new Email(array('message' => 'My custon message.'))
),
'subject' => array(
new NotBlank(array('message' => 'My custon message.')),
new Length(array('min' => 10), array('message' => 'My custon message.'))
),
'message' => array(
new NotBlank(array('message' => 'My custon message')),
new Length(array('min' => 5))
)
));
$resolver->setDefaults(array(
'constraints' => $collectionConstraint
));
}
public function getName()
{
return 'contact';
}
}
Thanks you all for your helping.
Best regards,
It's recommend to change the message of the assertion instead, but you can also use the invalid_message setting of a form type.