1

Context

I have a weird issue on my live environment that I have never seen on my local environment. Cache bins are disabled on my local environment and enabled on live server.

When clearing all caches on live server, the problem disappears for some time, then reappears. When disabling cache bins on live server the problem doesn't seem to happen anymore.

Issue

In my custom theme, I use a simple "Single field" template to override a given view field.

/**
 * @file
 * Theme override for a single field in a view.
 *
 * Available variables:
 * - view: The view that the field belongs to.
 * - field: The field handler that can process the input.
 * - row: The raw result of the database query that generated this field.
 * - output: The processed output that will normally be used.
 *
 * When fetching output from the row this construct should be used:
 * data = row[field.field_alias]
 *
 * The above will guarantee that you'll always get the correct data, regardless
 * of any changes in the aliasing that might happen if the view is modified.
 *
 * @see template_preprocess_views_view_field()
 */

In the output HTML of this field, I need a simple incremental id from 0 to n where n would be the total number of rows in the view results. Something like below for a View with 5 results:

<div data-index="0">...</div>
<div data-index="1">...</div>
<div data-index="2">...</div>
<div data-index="3">...</div>
<div data-index="4">...</div>

So in my field template, I use:

<div data-index="{{ row.index }}">...</div>

This works fine, except on some occasions, only on my live server with caching enabled where the output will be for example:

<div data-index="0">...</div>
<div data-index="1">...</div>
<div data-index="19">...</div>
<div data-index="3">...</div>
<div data-index="21">...</div>

Important notes:

  • I sometimes get indices such as 19 when there are only 10 or 15 results in the view so that number seems to come out of the blue.
  • This happens when the view is filtered using a single taxonomy term.

Question

Am I wrong assuming that row.index should give me an incremental sequence of integers for every view, with or without caching? If I am wrong, then what should I be using? And if not, what could cause this behavior?

4
  • 1
    The rendered result of a views row is cached and re-used even if displayed in a different row index. Did you try to configure caching for the specific View instead of disabling the render cache for the entire site?
    – 4uk4
    Oct 6, 2020 at 17:01
  • No I haven't yet. Do you suggest I disable caching on the View UI by setting Caching to none? Or should I go with time-based caching and disable only the query result or the rendered output? I am not sure what to do. Thanks.
    – MrUpsidown
    Oct 6, 2020 at 17:59
  • 1
    Yes, one of those should work. The issue here is with the rendered field template, so it should work if you only set the rendered output to Never Cache.
    – 4uk4
    Oct 6, 2020 at 19:10
  • Ok thanks a lot for your input. I will find another way to define that index then, as I'd really like to keep caching enabled on the view.
    – MrUpsidown
    Oct 6, 2020 at 20:36

2 Answers 2

2

To solve it using views-view-field.html.twig

First in view settings, add field "View Result Counter" and hide from display.

Now in your twig you can do

<div data-index="{{ view.field['counter'].getValue(row) }}">...</div>
2
  • 1
    +1, Views caching ignores the row index, but it shouldn't be able do this any longer for a real field. You can even get rid of the template by moving the Twig to "Rewrite Results" of the field.
    – 4uk4
    Oct 7, 2020 at 9:22
  • Nice. I had no idea we had that field available! Good to know ;)
    – MrUpsidown
    Oct 7, 2020 at 16:45
1

If I am wrong, then what should I be using?

Instead, you could do it using views-view--unformatted.html.twig

and modify the row part to

{% set count = 0 %}
{% for row in rows %}
  set count = count + 1
  {%
    set row_classes = [
      default_row_class ? 'views-row',
    ]
  %}
  <div data-index=count {{ row.attributes.addClass(row_classes) }}>
    {{ row.content }}
  </div>
{% endfor %}
2
  • There might be a creative way to solve via field template file, but I don't have access to Drupal right now. I'll look into it later.
    – No Sssweat
    Oct 6, 2020 at 19:36
  • 1
    That would not work if I really had to have that logic on field level, though it will work in my case if I adapt my logic a bit and move it up to the row level and that's actually exactly what I thought doing. Because I'd really like to not disable caching on the view as this seems to be my only option if I want to use row.index. So indeed it sounds like a better option to somehow define that variable increment by myself.
    – MrUpsidown
    Oct 6, 2020 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.