This used to work for me without fail when Drupal 8 first came out. However this does not seem to work anymore and I get an error. Drupal docs have always been horrid so no solution there.
custom.module
<?php
function custom_theme() {
$theme['home_page'] = [
'variables' => ['name' => NULL],
'template' => 'home_page'
];
return $theme;
}
function custom_menu(){
$items = array();
$items['admin/config/system/custom'] = array(
'title' => 'Custom',
'description' => 'Configuration Custom',
'route_name' => 'custom.settings'
);
return $items;
}
custom.routing.yml
custom.home:
path: /home
defaults:
_controller: Drupal\custom\Controller\RoutingController::home
requirements:
_permission: 'access content'
src/Controller/RoutingController.php
<?php
namespace Drupal\custom\Controller;
class RoutingController {
public function home(){
return array(
'#title' => 'Home',
'#theme' => 'home_page'
);
}
}
home_page.html.twig
<main>
<!-- some markup -->
</main>
your controller not extending the base controller class problem one
try this
namespace Drupal\custom\Controller;
use Drupal\Core\Controller\ControllerBase;
class RoutingController extends ControllerBase{
public function home(){
return array(
'#title' => 'Home',
'#theme' => 'home_page'
);
}
}
home_page.html.twig
<main>
<!-- some markup -->
{{ content }}
</main>
also try to extend you theme hook with path
'path' => drupal_get_path('module', 'custom') . '/templates',
and place your template twig file in your module/templates folder
Related
I'm trying to reach my first controller and view on a custom module with drupal 8. I'm new and this is my first custom module.
my_module.info.yaml located in /modules/custom/my_module
name: My Own Custom Module
description: A silly example module
type: module
core: 8.x
With this, I've been able to go to my extension to activate the module.
So, the module is installed.
Now, I want to try to hit my first twig template
In order to do so
my_module.routings.yaml located in /modules/custom/my_module
my_module.article_list:
path: 'my_module/articles'
defaults:
_controller: '\Drupal\my_module\Controller\ArticleController::page'
_title: "Title routing"
requirements:
_permissions: 'access content'
My controller located in /modules/custom/my_module/src/Controller
<?php
namespace Drupal\my_module\Controller;
class ArticleController{
public function page(){
$items = array(
array('name' => 'Article one'),
array('name' => 'Article 2')
array('name' => 'Article 3')
);
return array('#theme' => 'article_list',
'#items' => $items,
'#title' => 'Liste d\'article');
}
}
?>
article-list.html.twig located in /modules/custom/my_module/src/templates
<h4>{{ title }}</h4>
<ul>
{% for article in items %}
<li>{{article.title}}</li>
{% endfor %}
</ul>
my_module.module located in /modules/custom/my_module
<?php
function my_module_theme($existing, $type, $theme, $path){
return array('article_list' => array('variables' => array('items' => array(), 'title' => '')));
}
?>
But then, when I try to reach my template I hit a page not found
http://localhost:9000/drupal-8.7.8/index.php/my_module/articles
Thanks for your help.
It's not my_module.routings.yaml
but my_module.routing.yml
Also I think that path parameter must start with slash sign:
path: '/my_module/articles'
I am taking data from a config form and passing it to a .tpl file to display.
I am using hook_block_view() to take the data, put it into an array and send it to the .tpl file.
My code (on .module) is as such:
/**
* Implements hook_block_info().
*/
function message_block_info() {
return [
'message_block' => [
'info' => t('Message'),
'cache' => DRUPAL_CACHE_GLOBAL,
],
];
}
/**
* Implements hook_theme().
*/
function message_theme() {
return [
'message_block' => [
'template' => 'templates/message-block',
'variables' => [
'settings' => NULL,
'attributes' => [],
],
],
];
}
/**
* Implements hook_block_view().
*/
function message_block_view($delta = '') {
if ($delta !== 'message_block') {
return;
}
$config = message_default_settings();
dpm($config); // <- this shows correct data
$block['content'] = array(
'#theme' => 'message_block',
'#config' => array(
'message_text' => filter_xss($config['message_text']),
'message_link' => filter_xss($config['message_link']),
'message_button_text' => filter_xss($config['message_button_text']),
),
);
return $block;
}
And on the .tpl file:
<?php dpm('test'); //<- This works ?>
<?php dpm($config); //<- This does not work?>
<div class="message">
<?php print $config['message_text']; ?>
<?php if (!empty($config['message_link']) && !empty($config['alert_button_text'])): ?>
<a href="<?php print $config['message_link']; ?>" class="button">
<?php print $config['message_button_text']; ?>
</a>
<?php endif; ?>
</div>
I can place a dpm('test'); on the .tpl file and it will appear, so I know that the HTML is rendering. Obviously, I've tried clearing cache, too.
Would anyone know if I've missed a step to get this data appearing?
I found I was missing the config array initilisation in hook_theme:
function message_theme() {
return [
'message_block' => [
'template' => 'templates/message-block',
'variables' => [
'config' => NULL, //<- Was missing
],
],
];
}
Im new to drupal,I need to render a form so i have to implement hook theme, my confusion is Under which directory I should create hook theme file in drupal 8?
// my_module.module
function custom_module_theme($existing, $type, $theme, $path) {
return array(
'customize_form' => array(
'variables' => array(
'Custom_Form' => NULL
),
'render element' => 'form'
),
);
}
where I have to put above file in drupal 8??
Thanks in advance.
In your .module file
File location - module/custom/MODULENAME/MODULENAME.module
/**
* #file
* Twig template for render content
*/
function MODULENAME_theme($existing, $type, $theme, $path) {
return [
'theme_name_template' => [
'variables' => ['flag' => NULL],
],
];
}
To Use theme function use below code
return ['#theme' => 'theme_name_template', '#flag' => 1];
If i got it right you want the folder to place your module, right? You have to put your module in a folder under
/modules/custom/your_module_folder or /sites/all/modules/your_module_folder
Hy,
I'm really new to Zend-Framework 3 and I'm practicing OOP, I can't find a simple explanation/tutorial on making a Zend Form with a fieldset and legend. Basically I'm trying to create this in HTML:
<form name="my_name">
<fieldset>
<legend>My legend value</legend>
<input type="checkbox" name="name_1" value="value_1">Value 1</input>
<input type="checkbox" name="name_2" value="value_2">Value_2</input>
<input type="checkbox" name="name_3" value="value_3">Value_3</input>
</fieldset>
<input type="button" value="Get values" id="btn"/>
</form>
I checked the official documentation about Zend Forms and Collections and Fieldsets, but it's really confusing me. Any help would be greatly appreciated.
First, I am sorry as it is going to be a bit long one. But this would describe the form in action. So be patient please!
Assuming you are known to ZF3 default Application module. Some folders are created in the Application module for separation of each element. You need to create them as follows.
Let's get started by creating your fieldsets first. Zend\Form\Fieldset component represents a reusable set of elements and is dependent on Zend\From\Form component. This means you need to attach this to Zend\Form\Form.
module/Application/src/Form/Fieldset/YourFieldset.php
<?php
namespace Application\Form\Fieldset;
use Zend\Form\Element;
use Zend\Form\Fieldset;
class YourFieldset extends Fieldset
{
public function __construct($name = null)
{
parent::__construct('your-fieldset');
$this->add([
'name' => 'name_1',
'type' => Element\Checkbox::class,
'options' => [
'label' => 'Value 1',
'use_hidden_element' => true,
'checked_value' => 'yes',
'unchecked_value' => 'no',
],
'attributes' => [
'value' => 'no',
],
]);
// Creates others as your needs
}
}
Now we would create the form using Zend\From\Form attaching the fieldset created from Zend\From\Fieldset.
module/Application/src/Form/YourForm.php
<?php
namespace Application\Form;
use Application\Form\Fieldset\YourFieldset;
use Zend\Form\Form;
class YourForm extends Form
{
public function __construct($name = null)
{
parent::__construct('your-form');
$this->add([
// This name will be used to fetch each checkbox from
// the CheckboxFieldset::class in the view template.
'name' => 'fieldsets',
'type' => YourFieldset::class
]);
$this->add([
'name' => 'submit',
'attributes' => [
'type' => 'submit',
'value' => 'Get Values',
'class' => 'btn btn-primary'
],
]);
}
}
Our from is almost ready. We need to make it serviceable if we want it to be used in any action of a controller. So let's do that.
Update your module config file. If service_manager key does not exist then add the following snippet of code, otherwise, update only factories and aliases key as the following.
Fix namespaces in module config file.
module/Application/config/module.config.php
'service_manager' => [
'factories' => [
// Form service
Form\YourForm::class => Zend\ServiceManager\Factory\InvokableFactory::class,
// Other services
],
'aliases' => [
// Make an alias for the form service
'YourForm' => Form\YourForm::class,
],
],
Now the form is ready to be used. This needs to be injected into our controller. As I am working on Application module, I would inject the form into the IndexController::class's constructor. Then we would be using that form inside IndexController::fieldsetAction() method.
module/Application/src/Controller/IndexController.php
<?php
namespace Application\Controller;
use Zend\Form\FormInterface;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
protected $YourForm;
public function __construct(FormInterface $YourForm)
{
$this->YourForm = $YourForm;
}
public function fieldsetAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel(['form' => $this->YourForm]);
if (! $request->isPost()) {
return $viewModel;
}
$this->YourForm->setData($request->getPost());
if (! $this->YourForm->isValid()) {
return $viewModel;
}
$data = $this->YourForm->getData()['fieldsets'];
echo '<pre>';
print_r($data);
echo '</pre>';
return $viewModel;
}
}
As this controller is taking argument in its constructor, we need to create a factory for this controller (a factory creates other objects).
module/Application/src/Factory/Controller/IndexControllerFactory.php
<?php
namespace Application\Factory\Controller;
use Application\Controller\IndexController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class IndexControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// We get form service via service manager here
// and then inject controller's constructor
$YourForm = $container->get('YourForm');
return new IndexController($YourForm);
}
}
Once again, we need to update the module config file. We would add this time the factory under controllers key as follows
'controllers' => [
'factories' => [
Controller\IndexController::class => Factory\Controller\IndexControllerFactory::class,
],
],
At the end, echo the form in the view template as follows:
module/Application/view/application/index/fieldset.phtml
<h1>Checkbox Form</h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url());
// Here is the catch, remember this name from the CheckboxForm::class
$fieldset = $form->get('fieldsets');
$name_1 = $fieldset->get('name_1');
$name_2 = $fieldset->get('name_2');
$name_3 = $fieldset->get('name_3');
$submit = $form->get('submit');
$submit->setAttribute('class', 'btn btn-primary');
$form->prepare();
echo $this->form()->openTag($form);
?>
<fieldset>
<legend>My legend value</legend>
<?= $this->formElement($name_1) ?>
<?= $this->formLabel($name_1) ?>
<?= $this->formElement($name_2) ?>
<?= $this->formLabel($name_2) ?>
<?= $this->formElement($name_3) ?>
<?= $this->formLabel($name_3) ?>
<?= $this->formSubmit($submit) ?>
</fieldset>
<?php
echo $this->form()->closeTag();
Hope this would help you!
Actually the example you are looking for is in "collections" part of zend form. Its not the exact one but kinda like.
Here you are a little example. I ignored namespaces and hope so there's no typo :)
class myFieldset extends Fieldset {
public function init(){
$this
->add([
'name' => 'name_1,
'type' => 'text',
])
->add([
'name' => 'name_2,
'type' => 'text',
])
->add([
'name' => 'name_3,
'type' => 'text',
]);
}
}
class MyForm extends Form {
public function init(){
$this->add([
'type' => myFieldset,
'name' => 'fieldset'
])->add([
'type' => 'button',
'name' => 'action'
]);
}
}
And in view file;
<?=$this-form($form);?>
I have registered a dynamic sidebar as follows
register_sidebar(array(
'id' => 'widget-my-header',
'name' => 'My: Header',
'before_widget' => '',
'after_widget' => '',
'before_title' => '',
'after_title' => '',
));
I call the dynamic sidebar in my template.
dynamic_sidebar('widget-my-header');
Is it even possible to inject a custom function into that dynamic_sidebar('widget-my-header'); ?
Say I have a function add_my_cool_headline()
And I want that to be the content for this dynamic_sidebar('widget-my-header');
Can htis be done?
I'm using a child theme, so I'm looking to having to replace the dynamic_sidebar('widget-my-header'); with a custom action
I know how to insert my own action hook into every template page, however I'd really like to avoid that. As there are many many theme files where it needs to be changed.
Just make a class and register your widget in your sidebar
if ( function_exists('register_sidebar') ) {
register_sidebar(array('name' => 'widget-my-header','before_widget' => '<div class="widget">','after_widget' => '</div>','before_title' => '<span>','after_title' => '</span>'));
}
class MYHeaderWidget extends WP_Widget {
function MYHeaderWidget() {
//Constructor
$widget_ops = array('classname' => 'MYHeaderWidget Widget', 'description' => 'MYHeaderWidget' );
$this->WP_Widget('MYHeaderWidget', 'widget-my-header', $widget_ops);
}
function widget($args, $instance) {
// prints the widget
extract($args, EXTR_SKIP); ?>
<div class="">Hello</div>
<?php
}
}
register_widget('MYHeaderWidget');