Hi. I am developing a custom store item that uses some jqery and js to flip the store images (in this case tshirts) from front to back.
I have all working code and I have the twig for the page laying everything out well though I need to add some ids to divs E.G
<div id='%_side-1' class='flip'>
where % is the 'nid' of the product or some other custom id.
My question is what is the best way to achieve id=nid+_side-1?.

Comments

andyd328’s picture

To make the id available in a field template you can use a preprocess function in your theme such as:

function THEMENAME_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'ENTITY_TYPE' &&
    ($vars['element'] == 'FIELD_NAME'))) {
      $vars['node_id'] =  $vars['element']['#object']->id();
  }

}

You can then use the node_id variable in your field twig template:

<div id="{{ node_id }}_side-1" class="flip>...</div>

OR you can add the id in the preprocess and not in the template:

function THEMENAME_preprocess_field(&$vars, $hook) {
if ($vars['element']['#entity_type'] == 'ENTITY_TYPE' &&
    ($vars['element'] == 'FIELD_NAME'))) {
      $vars['attributes']['id']=  $vars['element']['#object']->id() . '_side-1';
  }

}

so long as your field template has the {{ attributes }} tag written into element the id will be output.

Firehawk777’s picture

Many thanks Andy.
That answers some huge questions. Though I am new to the hook_preprocess_hook() and I am not sure where I would implement it. IE in what file.

mmjvb’s picture

As the THEMENAME_preprocess_field already hinted at, the code needs to be placed in your THEMENAME.theme.
Suggest to use a sub theme for that, saves you from trouble when updating.

Firehawk777’s picture

So I tried adding this code into my theme (which is business_responsive_theme)

function business_responsive_theme_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'image' &&
    ($vars['element'] == 'field_female_front'))) {
      $vars['node_id'] =  $vars['element']['#object']->nid();
  }

}

and a few variations like $vars['node_id'] = $vars['element']['#object'].values->nid();and['element']['#object']['values']->nid() though it crashed the page. It appears that the nid is in #object.values though I am not sure of the syntax for this. nid is an array of 1 so I gather the value I am trying to get is field_female_front - #object - values - nid - 0

mmjvb’s picture

Try ->id() instead of ->nid().

Firehawk777’s picture

function business_responsive_theme_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'image' &&
    ($vars['element'] == 'field_back_female'))) {
      $vars['node_id'] =  $vars['element']['#object']['values']->id();
  }

}

and

function business_responsive_theme_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'image' &&
    ($vars['element'] == 'field_back_female'))) {
      $vars['node_id'] =  $vars['element']['#object']->id();
  }

}

I tried this. It did not cause the same error (this time a 500) error and it did not load either.

mmjvb’s picture

Suggest to enable error reporting to find out what you did wrong or check the log files on the webserver.

Firehawk777’s picture

Yes I had a syntax error.
I have fixed the error and the page loads fine. though I am still not getting the node_id to output and cannot see it in kint either.
This is the code I have been trying to use

function business_responsive_theme_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'image' &&
    ($vars['element'] == 'field_back_female')) {
     $vars['node_id'] =  $vars['element']['#object']['values']->nid();
  }

}

and

function business_responsive_theme_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'image' &&
    ($vars['element'] == 'field_back_female')) {
     $vars['node_id'] =  $vars['element']['#object']->nid();
  }

}

and I tried various versions including ->id() and still had no 'node_id' exposed either to the page or by kint so I dont even know if the 'field_back_female' is even being recognized by the preprocess function

mmjvb’s picture

the condition for the field name is wrong:
$vars['element'] == 'field_back_female') should be $vars['element']['#fieldname'] == 'field_back_female')

In addition when the first solution doesn't work, try the second.

Firehawk777’s picture

Thanks though still no luck with getting the field_back_female to register the new variable. I tried all the suggestions above and eventually tried this just to see if I could get any output.

function business_responsive_theme_preprocess_field(&$vars, $hook) {

if ($vars['element']['#entity_type'] == 'image' &&
   $vars['element']['#fieldname'] == 'field_back_female') {
   $vars['test_id'] = 'testId';
   $vars['attributes']['id']=  $vars['element']['#object']->id() . '_side-1';
   $vars['node_id'] =  $vars['element']['#object']['values']->nid();
  }

}

Also to make sure the attributes are exposed I wanted to use field--field-back-female.html.twig though I am not sure where to put the file to get it to register.

mmjvb’s picture

Suggest to have look in those modules to see whether they do something similar.

My understanding is that you should place it in the sub theme or your module. Most of the time placed in a folder "templates", possibly in subfolder "field". But the folder structure is for your own organization.
Assuming it is named according to the rules it will register automatically. Otherwise you need to add it as an suggestion.

andyd328’s picture

Are you sure your node/entity type is 'image'?

Firehawk777’s picture

Yes my entity is of type image. I still can get no return though I would like to say thanks to both of you for all your help at this point.
I am stoked to finally understand more about TWIG and its implementation in D8. Even tough I still can't get the return I want I am getting further than I have before.

andyd328’s picture

:-) it seems as though either the code isn't being run, or that its not being picked up in the template for some reason.

Can you try the below:

  1. Add a log statement inside the if statement to make sure that it is being run, if that log doesn't appear then there's something wrong with the if statement. https://drupalize.me/blog/201510/how-log-messages-drupal-8 . Clear your cache and reload the page. My guess is that you won't get a log, which would mean that either your entity isn't 'image' or the field isn't 'field_back_female'. You could also put kint($vars['element']['#entity_type']) in the function above the if statement and see what that gives you.
  2. If the above logged then try turning on Twig debugging - https://www.drupal.org/docs/8/theming/twig/debugging-twig-templates - and see what template is being used for your field. You may then need to create a new template/modify an existing one in your subtheme
Firehawk777’s picture

I tried this and though I know the function is being called I have unexpected returns. When I add the kint($vars['element']['#entity_type']);the fields I am interested in have an array of one argument and are called 'node'
When I trykint($vars['element']['#fieldname']);all fields seem to return NULL
I already have twig debugging turned on. Hence how I am finding out what variables are available.

andyd328’s picture

Sounds like your field could be on a node entity rather than an 'image' entity. have you tried

if ($vars['element']['#entity_type'] == 'node' &&
    ($vars['element'] == 'field_back_female'))) {
Firehawk777’s picture

I tried this though kint produced nothing

if ($vars['element']['#entity_type'] == 'node' &&
    $vars['element']['#fieldname'] == 'field_back_female') {
	kint($vars['element']);
}
andyd328’s picture

try it without the second condition

Firehawk777’s picture

I tried this though it had no return

if ($vars['element'] == 'node' &&
    $vars['element']['#fieldname'] == 'field_back_female') {
	kint($vars['element']);

  }

andyd328’s picture

Sorry, I meant try

if ($vars['element']['#entity_type'] == 'node') {

Firehawk777’s picture

Thanks I will try that. By the way I have another question that should be easier.
In the shirt custom content type I have a link and a logo. I want to make the logo use the link. I am having problems with getting just the url to be output in TWIG. The field is simply field_site_link. I have tried field_site_link.0 and field_site_link.0.url the first returns the url I want with part of another a tag with my home sites url and the other returns nothing.
so what I am trying to achieve is
<a class='shopItem-logo' href='{{ content._field_layout.content.field_site_link.0 }}'>{{ content._field_layout.content.field_logo }}</a>