Showing posts with label Theming. Show all posts
Showing posts with label Theming. Show all posts

Add a html field to a form in Drupal 8 & 9

 The Form API changed a bit over the years. This is the way add a html field to a form in Drupal 8 & 9.


$form['filed_name'] = [ '#markup' => '<h2>' . $node->get('field_name')->getString() . '$</h2>', ];


$form['filed_age'] = [ '#markup' => '<h4>' . $node->get('field_age')->getString() . '$</h4>', ];

Disable cache for a block in Drupal 8

 use $vars['#cache']['max-age'] = 0 to stop  block being cache in drupal 8.

**

 * Implements hook_preprocess_HOOK()

 */

function mytheme_preprocess_block(&$vars) {

  if($vars['derivative_plugin_id'] == 'block-id-name') {

    $vars['#cache']['max-age'] = 0;

  }

}

for custom Block you can use getCacheMaxAge() method like this

class MyModuleBlock extends BlockBase {

  /**

   * {@inheritdoc}

   */

  public function build() {

  }

  /**

   * @return int

   */

  public function getCacheMaxAge() {

    return 0;

  }

}


Also you can use \Drupal::service('page_cache_kill_switch')->trigger(); to disable the cache for anonymous users and all others too.

function fest_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

     if ($form_id == "node_something_form") {

            //disable the form cache for anonymous users and all others too

\Drupal::service('page_cache_kill_switch')->trigger();

}

}

How i get Taxonomy Term URL Path by tid and TID from Term Name in Drupal 8

For taxonomy term

$aliasManager = \Drupal::service('path_alias.manager');
$alias = $aliasManager->getAliasByPath('/taxonomy/term/'.$tidss);

 

For node 


$aliasManager = \Drupal::service('path_alias.manager');
$alias = $aliasManager->getAliasByPath('/node/'.$id);


Taxonomy term path alias in twig tpl

<a href="{{ path('entity.taxonomy_term.canonical', {'taxonomy_term': node.field_taxonomy_reference.entity.tid.value}) }}">
  <h2>{{ content.field_taxonomy_reference }}</h2>
</a>


To load a single term ID by term name and vocabulary in Drupal 8 you can use the following

$term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')

  ->loadByProperties(['name' => $term_name, 'vid' => 'job_category']);

$term = reset($term);

$term_id = $term->id();


Drupal 8 theming concepts

A theme is a collection of files that define the presentation layer. You can also create one or more "sub-themes" or variations on a theme. drupal.org/docs/8/theming.

The big change from Drupal 7 to Drupal 8 for theming is the change from PHP templates to twig and the use of yml "YAML" files.

CSS file organization

Drupal 8 follows the SMACSS-style categorization. (SMACSS = Scalable and modular architecture for css).

Base — CSS reset/normalize plus HTML element styling.
Layout — macro arrangement of a web page, including any grid systems.
Component — discrete, reusable UI elements.
State — styles that deal with client-side changes to components.
Theme — purely visual styling (“look-and-feel”) for a component.

CSS file naming conventions

CSS files should be placed in a css/ directory and broken down by module, theme, and admin files.
Note: Modules should never have any base styles. Drupal core's modules do not have any base styles. Instead Drupal core uses the Normalize.css library augmented with a drupal.base.css library.If a module attaches a CSS file to a template file, the CSS file should be named the same as the template file, e.g. the system-plugin-ui-form.html.twig CSS file should be named system-plugin-ui-form.css

YAML / YML

yaml  is a "human readable" markup language designed for data serialization for all programing languages.

Syntax for yml is key : value
Use a colon as a separator
Tabs are NOT allowed. Use spaces ONLY.
Properties and lists MUST be indented by two (2) spaces.
Yaml files end in the .yml file extension.
In Drupal 7, modules needed a MODULE_NAME.info file. Now, in Drupal 8 requires a MODULE_NAME.info.yml
Use yaml lint to find syntax errors. BLT can validate yml with blt validate:yaml.

Example - 

name: Hello World Module
description: Creates a page showing "Hello World".
package: Custom

type: module
core: 8.x

Libraries

Sometimes a site will require an external library. Libraries can be defined 3 different ways, within a theme, on a single page, or on a subset of pages with a preprocess function.

Each asset/library needs to be defined in the root of your module folder or in your theme root directory. For example the Drupal contrib module slick requires the external slick library. Inside of the theme directory docroot/themes/custom/MY_THEME there needs to be a MY_THEME.libraries.yml file.


slick:  
  version: 1.0.0  
  css:    
    theme:      
        stylesheets/ui/slick-rotator.css: {}


In the above example the theme key is for visual styling for a component. You can assign weights, or specify a theme. Therefore, in this example the asset/library slick has defined a css file included inside of the slick module directory.

Define a library on a single template

External libraries can increase the weight of a project and slow down a site's performance. If a custom javaScript library only needs to load on a single template, it might make sense to attach the library to only that template. For example, if you add attach_library to the top of twig template file, the library will only load whenever that twig template is used.

{# Place attach_library in a twig template. #}

{{ attach_library('THEME_NAME/library-name') }}

Define a library on a subset of pages

There can also be instances where you only need to add a library to a specific set of pages instead of every page. You can accomplish this with a preprocess function added the THEME_NAME.theme file.

function MY_THEME_page_attachments(array &$attachments) {

if (!\Drupal::currentUser()->hasPermission('access contextual links')) {  
  return;  

}

$attachments['#attached']['library'][] = 'contextual/drupal.contextual-links';

}

Adding stylesheets (CSS) and JavaScript (JS) to a Drupal theme

 Define all of your CSS and Javascript file or libraries in a *.libraries.yml file in your theme folder. If your theme is named custom, the file name should be custom.libraries.yml. Each "library" in the file is an entry detailing CSS and JS files (assets), like this.

# custom.libraries.yml

cuddly-slider:

  version: 1.x

  css:

    theme:

      css/cuddly-slider.css: {}

  js:

    js/cuddly-slider.js: {}

In this example, the JavaScript: cuddly-slider.js and CSS cuddly-slider.css are located in the respective js and css directories of your theme.

#Including jQuery in your Library

Remember, Drupal no longer loads jQuery on all pages by default, so for example if cuddly-slider needs jQuery you must declare a dependency on the core library that contains jQuery (Drupal core provides jQuery, not a module or theme). Declare the dependency with an extension name followed by a slash, followed by the library name, in this case core/jquery. If another library required cuddly-slider it would declare:custom/cuddly-slider, the theme name, followed by the library name. You cannot declare an individual file as a dependency, only a library.

So, to make jQuery available for cuddly-slider, we update the above to.

# custom.libraries.yml

cuddly-slider:

  version: 1.x


  css:

    theme:

      css/cuddly-slider.css: {}


  js:

    js/cuddly-slider.js: {}

  dependencies:

    - core/jquery


#Declaring dependencies

To declare a dependency, the required library is declared in the form resource/library. For core libraries, the resource is core, while for others it is the module name or the theme name. So if new_library is dependent on jQuery from core, my_library declared in my_theme, and my_library declared in my_module, you would declare the dependencies as.

# custom.libraries.yml

new_library:

  js:

    js/new_library.js: {}

  dependencies:

    - core/jquery

    - my_module/my_library

    - my_theme/my_library

The module and theme names provide namespacing for libraries of the same name.

#Attaching a library to all pages

Most themes will use a global-styling asset library, for the stylesheets (CSS files) that need to be loaded on every page where the theme is active. It is also possible to do with JS via a global-scripts asset library

# custom.libraries.yml (multiple libraries can be added to a libraries.yml file, these would appear below the cuddly-slider libraries added earlier)

global-styling:

  version: 1.x

  css:

    theme:

      css/layout.css: {}

      css/style.css: {}

      css/colors.css: {}

global-scripts:

  version: 1.x

  js: 

    js/navmenu.js: {}   

To be available everywhere in the theme, the global-styling/global-scripts libraries must then be added to your theme's info.yml (in this case custom.info.yml)

#custom.info.yml

name: Custom

type: theme

description: 'Custom theme'

core: 8.x

# by adding global-styling and global-scripts here, the css/js files in the library become 

# available to every page presented by the theme

libraries:

  - custom/global-styling

  - custom/global-scripts

base theme: classy

regions:

  header: Header

  content: Content

  sidebar_first: 'Sidebar first'

  footer: Footer


#Attaching a library via a Twig template

You can attach an asset library to a Twig template using the attach_library() function in any *.html.twig, file like so:


{{ attach_library('custom/cuddly-slider') }}

<div>Some fluffy markup {{ message }}</div>

#Attaching a library to a subset of pages

function custom_preprocess_page(&$variables) {

  $variables['page']['#cache']['contexts'][] = 'route';

  $route = "entity.node.preview";

  if (\Drupal::routeMatch()->getRouteName() === $route) {

    $variables['#attached']['library'][] = 'custom/node-preview';

  }

}




Drupal Theming - Use of template.php

 The template.php file contains your sub-theme's functions to manipulate Drupal's default markup. It is one of the most useful files when creating or modifying Drupal themes. 

template.php

A- It contains code that is run every time the template engine is run.

B- template.php is a collection of functions that assist in the theming of the site. It’s for all the conditional logic and data processing of the output - the place to redefine or override theme functions, or add variables that will be made available to the theme engine.

C- PHP: This file must start with a PHP opening tag and typically does not end with a PHP closing tag.

D- There will be one template.php file for a theme, and this one file will define any needed variables.

E- You can add new variables and template suggestions.

With template.php you ca do the following things.

1 - Modify any theme hooks variables or add your own variables, using preprocess or process functions.

2 - Override any theme function. That is, replace a module's default theme function with one you write.

3 - Call hook_*_alter() functions which allow you to alter various parts of Drupal's internals, including the render elements in forms. The most useful of which include hook_form_alter(), hook_form_FORM_ID_alter(), and hook_page_alter(). See api.drupal.org for more information about _alter functions.

Twig lower filter

 The lower filter converts a value to lowercase.

{{ 'WELCOME'|lower }}

{# outputs 'welcome' #}

Twig keys filter

 The keys filter returns the keys of an array. It is useful when you want to iterate over the keys of an array.

{% set sizes = [34, 36, 38, 40, 42] %}

{% for key in sizes|keys %}

    {{ key }}

{% endfor %}


Output

0

1

2

3

4


Twig first filter

 The first filter returns the first "element" of a sequence, a mapping, or a string:

{{ [1, 2, 3, 4]|first }}

{# outputs 1 #}


{{ { a: 1, b: 2, c: 3, d: 4 }|first }}

{# outputs 1 #}


{{ '1234'|first }}

{# outputs 1 #}

Twig upper filter

 The upper filter converts a value to uppercase:

{{ 'welcome'|upper }}

{# outputs 'WELCOME' #}

Twig trim filter

 The trim filter strips whitespace (or other characters) from the beginning and end of a string.

{{ '  I like Twig.  '|trim }}

{# outputs 'I like Twig.' #}

{{ '  I like Twig.'|trim('.') }}

{# outputs '  I like Twig' #}

{{ '  I like Twig.  '|trim(side='left') }}

{# outputs 'I like Twig.  ' #}

{{ '  I like Twig.  '|trim(' ', 'right') }}

{# outputs '  I like Twig.' #}

Arguments

character_mask: The characters to strip

side: The default is to strip from the left and the right (`both`) sides, but `left` and `right` will strip from either the left side or right side only

Twig title filter

 The title filter returns a titlecased version of the value. Words will start with uppercase letters, all remaining characters are lowercase:

{{ 'my first car'|title }}

{# outputs 'My First Car' #}

Twig date_modify filter

 The date_modify filter modifies a date with a given modifier string:

{{ post.published_at|date_modify("+1 day")|date("m/d/Y") }}

The date_modify filter accepts strings (it must be in a format supported by the strtotime function) or DateTime instances. You can combine it with the date filter for formatting.


Arguments

modifier: The modifier

Twig date filter

 The date filter formats a date to a given format.

{{ post.published_at|date("m/d/Y") }}

The format specifier is the same as supported by date, except when the filtered data is of type DateInterval, when the format must conform to DateInterval::format instead.

The date filter accepts strings (it must be in a format supported by the strtotime function), DateTime instances, or DateInterval instances. For instance, to display the current date, filter the word "now".

{{ "now"|date("m/d/Y") }}

To escape words and characters in the date format use \\ in front of each character.

{{ post.published_at|date("F jS \\a\\t g:ia") }}

If the value passed to the date filter is null, it will return the current date by default. If an empty string is desired instead of the current date, use a ternary operator:

{{ post.published_at is empty ? "" : post.published_at|date("m/d/Y") }}

If no format is provided, Twig will use the default one: F j, Y H:i. This default can be changed by calling the setDateFormat() method on the core extension instance. The first argument is the default format for dates and the second one is the default format for date intervals.

$twig = new \Twig\Environment($loader);

$twig->getExtension(\Twig\Extension\CoreExtension::class)->setDateFormat('d/m/Y', '%d days');

Timezone

By default, the date is displayed by applying the default timezone (the one specified in php.ini or declared in Twig -- see below), but you can override it by explicitly specifying a timezone:

{{ post.published_at|date("m/d/Y", "Europe/Paris") }}

If the date is already a DateTime object, and if you want to keep its current timezone, pass false as the timezone value:

{{ post.published_at|date("m/d/Y", false) }}

The default timezone can also be set globally by calling setTimezone():

$twig = new \Twig\Environment($loader);

$twig->getExtension(\Twig\Extension\CoreExtension::class)->setTimezone('Europe/Paris');

Arguments

format: The date format

timezone: The date timezone

Twig convert_encoding filter

 The convert_encoding filter converts a string from one encoding to another. The first argument is the expected output charset and the second one is the input charset:


{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}

Arguments

to: The output charset

from: The input charset

Twig column filter

 The column filter returns the values from a single column in the input array.


{% set items = [{ 'fruit' : 'apple'}, {'fruit' : 'orange' }] %}


{% set fruits = items|column('fruit') %}


{# fruits now contains ['apple', 'orange'] #}

Twig capitalize filter

 The capitalize filter capitalizes a value. The first character will be uppercase, all others lowercase:


{{ 'my first car'|capitalize }}


{# outputs 'My first car' #}

Twig batch filter

 The batch filter "batches" items by returning a list of lists with the given number of items. A second parameter can be provided and used to fill in missing items:

{% set items = ['a', 'b', 'c', 'd'] %}

<table>

{% for row in items|batch(3, 'No item') %}

    <tr>

        {% for column in row %}

            <td>{{ column }}</td>

        {% endfor %}

    </tr>

{% endfor %}

</table>

The above example will be rendered as.

<table>

    <tr>

        <td>a</td>

        <td>b</td>

        <td>c</td>

    </tr>

    <tr>

        <td>d</td>

        <td>No item</td>

        <td>No item</td>

    </tr>

</table>

Twig abs filter

 The abs filter returns the absolute value.

{% set number = -10 %}

{{ number|abs }}

{# output 10 #}

Twig split filter

 The split filter splits a string by the given delimiter and returns a list of strings.

If you want to split a url , use split filter, suppose you have a url public://Quarterly/2019-07/sample.pdf.

And you want to print only 2019-07 , you can use split filter 

Example 

{% set foo = "public://Quarterly/2019-07/sample.pdf"|split('/') %}

{# foo contains ['public:', '', 'Quarterly' , '2019-07','sample.pdf'] #}

for printing 2019-09  ,  use {{ foo.3 }}

You can also pass a limit argument

A- If limit is positive, the returned array will contain a maximum of limit elements with the last element containing the rest of string;

B- If limit is negative, all components except the last -limit are returned;

C- If limit is zero, then this is treated as 1.


{% set foo = "one,two,three,four,five"|split(',', 3) %}

{# foo contains ['one', 'two', 'three,four,five'] #}

If the delimiter is an empty string, then value will be split by equal chunks. Length is set by the limit argument (one character by default).


{% set foo = "123"|split('') %}

{# foo contains ['1', '2', '3'] #}


{% set bar = "aabbcc"|split('', 2) %}

{# bar contains ['aa', 'bb', 'cc'] #}

Write a program in PHP to reverse a number

A number can be written in reverse order. For example 12345 = 54321 <?php   $ num = 23456;   $ revnum = 0;   while ($ num > 1)   {   $...