Answers.Body: <p>Your entry detail page needs to be aware of the filters applied on the overview page in order for this to work. I see a couple of ways to do this:</p>
  <ol>
  <li>Whenever the filters change, use JS to make an AJAX call that passes the selected filters to a custom controller action. This controller then saves the filters in the session, then the entry detail page can use it the filters as parameters for <code>getNext()</code> / <code>getPrevious()</code>. This is a bit flimsy, since it can easily break and might result in unexpected behaviour if the user visits other pages in the meantime.</li>
  <li>Whenever a filter changes, dynamically modify the links to the entries on your overview page with JS to include the current filters as GET parameters. Then the entry page can read those parameters from the request to get the next / previous entry. This requires you to replicate the filtering logic in your backend template and make sure the JS-based filtering works exactly like the backend query.</li>
  <li>Same as 2, but instead of passing parameters, pass the ID of the previous / next entry directly.</li>
  </ol>
  <p>I'd say the most robust solution is #2. The easiest would be #3.</p>
  <h2>Sample code for approach #3</h2>
  <p>For this to work, you'd need to adjust your overview template so the entries list includes the entries' IDs:</p>
  <pre><code>&lt;ul class=&quot;entry-list&quot;&gt;
      {% for item in craft.entries().section('kelims').all() %}
          &lt;li class=&quot;entry-list__item&quot; data-entry-id=&quot;{{ item.id }}&quot;&gt;
              &lt;a href=&quot;{{ entry.url }}&quot; class=&quot;entry-list__link&quot;&gt;
                  {{- item.title -}}
              &lt;/a&gt;
          &lt;/li&gt;
      {% endfor %}
  &lt;/ul&gt;
  </code></pre>
  <p>Then whenever the filters changes, after you have filtered the entries with JS, add the ID of the previous / next entry to the URL. Quick and might contain errors, but you get the idea:</p>
  <pre class="lang-js prettyprint-override"><code>const refreshEntryLinks = () =&gt; {
      const entryList = document.querySelector('.entry-list');
      const visibleEntries = Array.from(entryList.querySelectorAll('.entry-list__item'))
          // filter out hidden entries (this assumes elements are hidden with the `hidden` attribute)
          .filter(entry =&gt; !entry.hidden);
      visibleEntries.forEach((entry, index) =&gt; {
          const link = entry.querySelector('.entry-list__link')
          const prevIndex = index &gt; 0 ? index - 1 : null;
          const nextIndex = index &lt; visibleEntries.length - 1 ? index + 1 : null;
          const addParams = new URLSearchParams;
          if (null !== prevIndex) {
              const prevId = visibleEntries[prevIndex].dataset.entryId;
              addParams.append('prevId', prevId);
          }
          if (null !== nextIndex) {
              const nextId = visibleEntries[nextIndex].dataset.entryId;
              addParams.append('nextId', nextId);
          }
          const modifiedUrl = new URL(link.href);
          modifiedUrl.search = addParams;
          link.href = modifiedUrl;
      });
  }
  </code></pre>
  <p>Finally, you can use the <code>prevId</code> and <code>nextId</code> parameters added to the URL in the detail page to display links to those entries:</p>
  <pre><code>{% set prevId = craft.request.getQuery('prevId') %}
  {% set nextId = craft.request.getQuery('nextId') %}
  {% set prevEntry = prevId ? craft.entries.section('kelims').id(prevId).one() : null %}
  {% set nextEntry = nextId ? craft.entries.section('kelims').id(nextId).one() : null %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T08:40:57.910Z
Answers.Text: Thanks! it does not get/find the `prevID` or `nextID`. Maybe the filter you applied `!entry.hidden` does not work? What exactly do you mean by the hidden attribute? I have set a class of "hide" or "block, after unchecking the checkbox.
Answers.UserDisplayName: Henrik
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T08:42:04.057Z
Answers.Text: I edited my question as well. hope this is understandable.
Answers.UserDisplayName: Henrik
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T08:48:56.857Z
Answers.Text: @Henrik In your JS-based filter, how are you hiding the entries that don't match the selected filters? The code sample above assumes you're using the [hidden Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden). If you're using a class or setting `display: none;` manually, you need to adjust the condition in the `filter` callback. For example: `.filter(entry => !entry.classList.contains('is-hidden'))`.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T08:51:12.440Z
Answers.Text: @Henrik In regards to your edit: Your proposed solution is approach #2 in my answer. The JS code would be similar to my sample code posted here. Only instead of adding the IDs of the previous / next entries, you would be adding the selected category IDs to the URL so you can filter entries in the backend based on that. I could try to write some sample code for that as well, but you'd need to post your overview template and preferrably the JS filtering code for that so I don't have to make guesses regarding your HTML structure :)
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T09:14:46.990Z
Answers.Text: thanks, i adjusted the code with the correct class, but it still gives me the `Variable "prevEntry" does not exist.`. Totally understand, i will try to post my code as readable as possible. The code is quite old now, i got it from another question asked here, and it just worked well for me. Although i only understand half of it, i am the "learning by doing" js-guy, which makes it sometimes quite hard :).
Answers.UserDisplayName: Henrik
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T09:43:28.397Z
Answers.Text: @Henrik Ok that JS filtering code is _way_ overcomplicated ^^ The error message comes from twig? Note that the `prevEntry` / `nextEntry` will only exist if the current entry isn't the first/last entry in the filtered list, respectively. So your template will need to handle this case. I've adjusted the Twig code to always set the variables, but set them to null if the prevId / nextId aren't set.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T11:56:54.867Z
Answers.Text: i was afraid of it. Yes, it comes from twig. with your adjustment it is gone, but `nexId/prevId` are empty. maybe i do not understand your refreshEntryLinks function correctly: do i have to modify other places in the twig file, according to your script? as i understand it, `nexId/prevId` gets popuplated automatically and i can you it then in the entry.twig file (the twig file for the detail page)
Answers.UserDisplayName: Henrik
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T13:39:36.427Z
Answers.Text: @Henrik Given your template structure, you will need to adjust the code a bit: 1. Find the parent element (change the `.entry-list` selector to `.result`. 2. Find all visible entries (change the `.entry-list__item` selector to `.result__item` and change the filter condition: `!entry.classList.contains('hide')`). 3. Get the prev/next element in the array of visible entries to get their IDs from the data-entry-id attribute, no change needed. 4. Modify the anchor element to include the prevId/nextId in the href (change the link selector from `entry-list__link` to `.result__link`).
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T13:40:44.440Z
Answers.Text: The other option (#2 in my list) would be to add the selected category IDs to the links instead of adding the prev/next entry IDs directly. This would be even more involved though, especially in terms of server-side code.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T14:19:14.263Z
Answers.Text: these adjustments i already did, this understanding of your code i have ;). but no luck. To add the selected category IDs to the links, this is what i dont get. is this covered in the last part of your code (modifiedUrl)? I tried to edit the {{entry.url)), but no luck
Answers.UserDisplayName: Henrik
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T14:25:00.127Z
Answers.Text: @Henrik No, my sample code follows approach #3. If you want to go with approach #2 instead, you could throw out 90% of the JS code. Just loop through all the entry links and add the selected category IDs to them. Check the part of my code using URLSearchParams on how to add query parameters to existing links. However, then you also have to adjust your backend code to read those parameters and add them to the params for `getNext` / `getPrev`.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-28T07:55:19.517Z
Answers.LastActivityDate: 2021-05-28T14:26:16.657Z
Answers.LastEditDate: 2021-05-28T14:26:16.657Z
Answers.UserDisplayName: MoritzLost
Body: <p>I have a section, where i display a list of entries from a structure.
  The section is an overview page, where the entries are listed with a picture and title.</p>
  <p>If the user clicks on an image, a detail (entry)- page is shown, where it is possible to jump right away to the next entry, instead of going back to the overview.
  works fine with:</p>
  <pre><code> {% set params = craft.entries.section('kelims') %}
   {% set prevEntry = entry.getPrev(params) %}
   {% set nextEntry = entry.getNext(params) %}
  </code></pre>
  <p>there is also a filter on the overview page, where the user can choose from multiple categories and display the entries, based on checkboxes. each checkbox represents a category and depending on what checkbox is clicked, the entry gets a class to hide or show it. so entries are shown without page-reload.
  each entry has multiple categories.</p>
  <p>now if a user uses theses filters and the clicks a detail page, and then wants to get to the next entry (with the <code>{% set prevEntry = entry.getPrev(params) %}</code> it does not work anymore.
  because the param does not reflect the new classes to hide or show the entry.</p>
  <p>is there a way to alter the param settings?
  or how to i get this working?</p>
  <p><strong>More explanation for the setup</strong>:  i have 4 Category Groups with several categories. The use can click multiple and they filter by AND.
  So there are <code>catPlace</code>, <code>catTime</code>, <code>catSize</code>, <code>catType</code></p>
  <p><strong>EDIT</strong>:
  After googling and asking, this should be the theory for the solution, but i dont know how to put into code:</p>
  <p>with <code>craft.app.request.getQueryParam</code> i fetch the ids of the different category-groups and append them to the url of the item-link, like <code>?caPlace=72&amp;catTime=123</code>, and use this on the Detailpage for the getPrev()/getNext()</p>
  <p><strong>EDIT 2</strong>
  The Section Overview Page Looks like this:</p>
  <pre><code>{% set categoriesObject = craft.categories.group('catObject').all() %}
  {% set categoriesSize = craft.categories.group('catSize').all() %}
  {% set categoriesProvenienz = craft.categories.group('catProvenienz').all() %}
  {% set categoriesYear = craft.categories.group('catYear').all() %}
  
  &lt;div class=&quot;content-grid filter-wrap result&quot; id=&quot;filter-wrap&quot;&gt;
  {# {% set kelims = entry.kelimsEntrieField.all() %} #}
  {% set kelims = craft.entries.section('kelims') %}
  
  {% for entry in kelims %}
  
  {# Fetch all of the categories related to this entry #}
  {% set categories = craft.categories.relatedTo(entry).ids() %}
  
      
      {% set favIdStringClass = categories|join(' ') %}
      {% set favIdStringData = categories|join(',') %}
      {% set catGroupId = entry.FilterCatObject %}
      {% set kelimImage = entry.kelimImage.one().getUrl('kelimthumb')|default('https://dummyimage.com/600x600/d1d1d1/d1d1d1.png&amp;text=Sample') %}
      
          &lt;div class=&quot;result__item&quot; data-entry-id=&quot;{{ entry.id }}&quot;&gt;
              &lt;a href=&quot;{{entry.url}}&quot; class=&quot;content-grid__box filter-item result__link {{favIdStringClass}}&quot;&gt;
              
                  &lt;div 
                  style=&quot;background-image: url( {{kelimImage}} );&quot;
                  loading=&quot;lazy&quot;
                  class=&quot;bgimage lazy&quot;
                  &gt;
                      &lt;h2 class=&quot;content-grid__box-title&quot;&gt;{{ entry.title }}&lt;/h2&gt;
                  &lt;/div&gt;
              &lt;/a&gt;
          &lt;/div&gt;
      {% endfor %}
      
  &lt;/div&gt;
  </code></pre>
  <p>and the script for the Filtering:</p>
  <pre><code>function change() {
    const catObject = document.querySelectorAll(&quot;.catObject input[type='checkbox']&quot;);
    const catSize = document.querySelectorAll(&quot;.catSize input[type='checkbox']&quot;);
    const catProvenienz = document.querySelectorAll(&quot;.catProvenienz input[type='checkbox']&quot;);
    const catYear = document.querySelectorAll(&quot;.catYear input[type='checkbox']&quot;);
    const filters = {
      Cobject: getClassOfCheckedCheckboxes(catObject),
      Csize: getClassOfCheckedCheckboxes(catSize),
      Cprovenienz: getClassOfCheckedCheckboxes(catProvenienz),
      Cyear: getClassOfCheckedCheckboxes(catYear),
    };
    
    filterResults(filters);
  }
  
  function getClassOfCheckedCheckboxes(checkboxes) {
    const classes = [];
    
    if (checkboxes &amp;&amp; checkboxes.length &gt; 0) {
      for (let i = 0; i &lt; checkboxes.length; i++) {
        const cb = checkboxes[i];
        
        if (cb.checked) {
          classes.push(cb.getAttribute('data-value'));
        }
      }
    }
    
    return classes;
  }
  
  function filterResults(filters) {
    const rElems = document.querySelectorAll('.result a');
    const hiddenElems = [];
    
    if (!rElems || rElems.length &lt;= 0) {
      return;
    }
    
    for (var i = 0; i &lt; rElems.length; i++) {
      const el = rElems[i];
  
      if (filters.Cobject.length &gt; 0) {
        var isHidden = true;
  
        for (var j = 0; j &lt; filters.Cobject.length; j++) {
          var filter = filters.Cobject[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
  
      if (filters.Csize.length &gt; 0) {
        var isHidden = true;
  
        for (var j = 0; j &lt; filters.Csize.length; j++) {
          var filter = filters.Csize[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
      
  
      if (filters.Cprovenienz.length &gt; 0) {
        var isHidden = true;
  
        for (var j = 0; j &lt; filters.Cprovenienz.length; j++) {
          var filter = filters.Cprovenienz[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
  
  
      // Year
      if (filters.Cyear.length &gt; 0) {
        var isHidden = true;
  
        for (var j = 0; j &lt; filters.Cyear.length; j++) {
          var filter = filters.Cyear[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
    }
  
    for (var i = 0; i &lt; rElems.length; i++) {
      // rElems[i].style.display = &quot;block&quot;;
      rElems[i].classList.remove('hide');
      rElems[i].classList.add('block');
    }
  
    if (hiddenElems.length &lt;= 0) {
      return;
    }
  
    for (var i = 0; i &lt; hiddenElems.length; i++) {
      // hiddenElems[i].style.display = &quot;none&quot;;
      hiddenElems[i].classList.add('hide');
      hiddenElems[i].classList.remove('block');
    }
  }
  </code></pre>
  
Tags: <entry><filter><previous-next>
Title: get next entry with entry.getNext(), based on a multiple category filter
ThreadText: # get next entry with entry.getNext(), based on a multiple category filter
  
  (Asked by: username_0 on 2021-05-27)
  
  I have a section, where i display a list of entries from a structure.
  The section is an overview page, where the entries are listed with a picture and title.
  
  If the user clicks on an image, a detail (entry)- page is shown, where it is possible to jump right away to the next entry, instead of going back to the overview.
  works fine with:
  
  ```
   {% set params = craft.entries.section('kelims') %}
   {% set prevEntry = entry.getPrev(params) %}
   {% set nextEntry = entry.getNext(params) %}
  
  ```
  
  there is also a filter on the overview page, where the user can choose from multiple categories and display the entries, based on checkboxes. each checkbox represents a category and depending on what checkbox is clicked, the entry gets a class to hide or show it. so entries are shown without page-reload.
  each entry has multiple categories.
  
  now if a user uses theses filters and the clicks a detail page, and then wants to get to the next entry (with the `{% set prevEntry = entry.getPrev(params) %}` it does not work anymore.
  because the param does not reflect the new classes to hide or show the entry.
  
  is there a way to alter the param settings?
  or how to i get this working?
  
  **More explanation for the setup**: i have 4 Category Groups with several categories. The use can click multiple and they filter by AND.
  So there are `catPlace`, `catTime`, `catSize`, `catType`
  
  **EDIT**:
  After googling and asking, this should be the theory for the solution, but i dont know how to put into code:
  
  with `craft.app.request.getQueryParam` i fetch the ids of the different category-groups and append them to the url of the item-link, like `?caPlace=72&catTime=123`, and use this on the Detailpage for the getPrev()/getNext()
  
  **EDIT 2**
  The Section Overview Page Looks like this:
  
  ```
  {% set categoriesObject = craft.categories.group('catObject').all() %}
  {% set categoriesSize = craft.categories.group('catSize').all() %}
  {% set categoriesProvenienz = craft.categories.group('catProvenienz').all() %}
  {% set categoriesYear = craft.categories.group('catYear').all() %}
  
  <div class="content-grid filter-wrap result" id="filter-wrap">
  {# {% set kelims = entry.kelimsEntrieField.all() %} #}
  {% set kelims = craft.entries.section('kelims') %}
  
  {% for entry in kelims %}
  
  {# Fetch all of the categories related to this entry #}
  {% set categories = craft.categories.relatedTo(entry).ids() %}
  
      
      {% set favIdStringClass = categories|join(' ') %}
      {% set favIdStringData = categories|join(',') %}
      {% set catGroupId = entry.FilterCatObject %}
      {% set kelimImage = entry.kelimImage.one().getUrl('kelimthumb')|default('https://dummyimage.com/600x600/d1d1d1/d1d1d1.png&text=Sample') %}
      
          <div class="result__item" data-entry-id="{{ entry.id }}">
              <a href="{{entry.url}}" class="content-grid__box filter-item result__link {{favIdStringClass}}">
              
                  <div 
                  style="background-image: url( {{kelimImage}} );"
                  loading="lazy"
                  class="bgimage lazy"
                  >
                      <h2 class="content-grid__box-title">{{ entry.title }}</h2>
                  </div>
              </a>
          </div>
      {% endfor %}
      
  </div>
  
  ```
  
  and the script for the Filtering:
  
  ```
  function change() {
    const catObject = document.querySelectorAll(".catObject input[type='checkbox']");
    const catSize = document.querySelectorAll(".catSize input[type='checkbox']");
    const catProvenienz = document.querySelectorAll(".catProvenienz input[type='checkbox']");
    const catYear = document.querySelectorAll(".catYear input[type='checkbox']");
    const filters = {
      Cobject: getClassOfCheckedCheckboxes(catObject),
      Csize: getClassOfCheckedCheckboxes(catSize),
      Cprovenienz: getClassOfCheckedCheckboxes(catProvenienz),
      Cyear: getClassOfCheckedCheckboxes(catYear),
    };
    
    filterResults(filters);
  }
  
  function getClassOfCheckedCheckboxes(checkboxes) {
    const classes = [];
    
    if (checkboxes && checkboxes.length > 0) {
      for (let i = 0; i < checkboxes.length; i++) {
        const cb = checkboxes[i];
        
        if (cb.checked) {
          classes.push(cb.getAttribute('data-value'));
        }
      }
    }
    
    return classes;
  }
  
  function filterResults(filters) {
    const rElems = document.querySelectorAll('.result a');
    const hiddenElems = [];
    
    if (!rElems || rElems.length <= 0) {
      return;
    }
    
    for (var i = 0; i < rElems.length; i++) {
      const el = rElems[i];
  
      if (filters.Cobject.length > 0) {
        var isHidden = true;
  
        for (var j = 0; j < filters.Cobject.length; j++) {
          var filter = filters.Cobject[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
  
      if (filters.Csize.length > 0) {
        var isHidden = true;
  
        for (var j = 0; j < filters.Csize.length; j++) {
          var filter = filters.Csize[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
      
  
      if (filters.Cprovenienz.length > 0) {
        var isHidden = true;
  
        for (var j = 0; j < filters.Cprovenienz.length; j++) {
          var filter = filters.Cprovenienz[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
  
      // Year
      if (filters.Cyear.length > 0) {
        var isHidden = true;
  
        for (var j = 0; j < filters.Cyear.length; j++) {
          var filter = filters.Cyear[j];
  
          if (el.classList.contains(filter)) {
            isHidden = false;
            break;
          }
        }
  
        if (isHidden) {
          hiddenElems.push(el);
        }
      }
    }
  
    for (var i = 0; i < rElems.length; i++) {
      // rElems[i].style.display = "block";
      rElems[i].classList.remove('hide');
      rElems[i].classList.add('block');
    }
  
    if (hiddenElems.length <= 0) {
      return;
    }
  
    for (var i = 0; i < hiddenElems.length; i++) {
      // hiddenElems[i].style.display = "none";
      hiddenElems[i].classList.add('hide');
      hiddenElems[i].classList.remove('block');
    }
  }
  
  ```
  
  **Tags:** entry, filter, previous-next
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-05-28. Score: 1
  
  Your entry detail page needs to be aware of the filters applied on the overview page in order for this to work. I see a couple of ways to do this:
  
  1. Whenever the filters change, use JS to make an AJAX call that passes the selected filters to a custom controller action. This controller then saves the filters in the session, then the entry detail page can use it the filters as parameters for `getNext()` / `getPrevious()`. This is a bit flimsy, since it can easily break and might result in unexpected behaviour if the user visits other pages in the meantime.
  2. Whenever a filter changes, dynamically modify the links to the entries on your overview page with JS to include the current filters as GET parameters. Then the entry page can read those parameters from the request to get the next / previous entry. This requires you to replicate the filtering logic in your backend template and make sure the JS-based filtering works exactly like the backend query.
  3. Same as 2, but instead of passing parameters, pass the ID of the previous / next entry directly.
  
  I'd say the most robust solution is #2. The easiest would be #3.
  
  ## Sample code for approach #3
  
  For this to work, you'd need to adjust your overview template so the entries list includes the entries' IDs:
  
  ```
  <ul class="entry-list">
      {% for item in craft.entries().section('kelims').all() %}
          <li class="entry-list__item" data-entry-id="{{ item.id }}">
              <a href="{{ entry.url }}" class="entry-list__link">
                  {{- item.title -}}
              </a>
          </li>
      {% endfor %}
  </ul>
  
  ```
  
  Then whenever the filters changes, after you have filtered the entries with JS, add the ID of the previous / next entry to the URL. Quick and might contain errors, but you get the idea:
  
  ```js
  const refreshEntryLinks = () => {
      const entryList = document.querySelector('.entry-list');
      const visibleEntries = Array.from(entryList.querySelectorAll('.entry-list__item'))
          // filter out hidden entries (this assumes elements are hidden with the `hidden` attribute)
          .filter(entry => !entry.hidden);
      visibleEntries.forEach((entry, index) => {
          const link = entry.querySelector('.entry-list__link')
          const prevIndex = index > 0 ? index - 1 : null;
          const nextIndex = index < visibleEntries.length - 1 ? index + 1 : null;
          const addParams = new URLSearchParams;
          if (null !== prevIndex) {
              const prevId = visibleEntries[prevIndex].dataset.entryId;
              addParams.append('prevId', prevId);
          }
          if (null !== nextIndex) {
              const nextId = visibleEntries[nextIndex].dataset.entryId;
              addParams.append('nextId', nextId);
          }
          const modifiedUrl = new URL(link.href);
          modifiedUrl.search = addParams;
          link.href = modifiedUrl;
      });
  }
  
  ```
  
  Finally, you can use the `prevId` and `nextId` parameters added to the URL in the detail page to display links to those entries:
  
  ```
  {% set prevId = craft.request.getQuery('prevId') %}
  {% set nextId = craft.request.getQuery('nextId') %}
  {% set prevEntry = prevId ? craft.entries.section('kelims').id(prevId).one() : null %}
  {% set nextEntry = nextId ? craft.entries.section('kelims').id(nextId).one() : null %}
  
  ```
  
  > **Comments:**
  > **username_0**: Thanks! it does not get/find the `prevID` or `nextID`. Maybe the filter you applied `!entry.hidden` does not work? What exactly do you mean by the hidden attribute? I have set a class of "hide" or "block, after unchecking the checkbox.  
  > **username_0**: I edited my question as well. hope this is understandable.  
  > **username_1**: @username_0 In your JS-based filter, how are you hiding the entries that don't match the selected filters? The code sample above assumes you're using the [hidden Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden). If you're using a class or setting `display: none;` manually, you need to adjust the condition in the `filter` callback. For example: `.filter(entry => !entry.classList.contains('is-hidden'))`.  
  > **username_1**: @username_0 In regards to your edit: Your proposed solution is approach #2 in my answer. The JS code would be similar to my sample code posted here. Only instead of adding the IDs of the previous / next entries, you would be adding the selected category IDs to the URL so you can filter entries in the backend based on that. I could try to write some sample code for that as well, but you'd need to post your overview template and preferrably the JS filtering code for that so I don't have to make guesses regarding your HTML structure :)  
  > **username_0**: thanks, i adjusted the code with the correct class, but it still gives me the `Variable "prevEntry" does not exist.`. Totally understand, i will try to post my code as readable as possible. The code is quite old now, i got it from another question asked here, and it just worked well for me. Although i only understand half of it, i am the "learning by doing" js-guy, which makes it sometimes quite hard :).  
  > **username_1**: @username_0 Ok that JS filtering code is _way_ overcomplicated ^^ The error message comes from twig? Note that the `prevEntry` / `nextEntry` will only exist if the current entry isn't the first/last entry in the filtered list, respectively. So your template will need to handle this case. I've adjusted the Twig code to always set the variables, but set them to null if the prevId / nextId aren't set.  
  > **username_0**: i was afraid of it. Yes, it comes from twig. with your adjustment it is gone, but `nexId/prevId` are empty. maybe i do not understand your refreshEntryLinks function correctly: do i have to modify other places in the twig file, according to your script? as i understand it, `nexId/prevId` gets popuplated automatically and i can you it then in the entry.twig file (the twig file for the detail page)  
  > **username_1**: @username_0 Given your template structure, you will need to adjust the code a bit: 1. Find the parent element (change the `.entry-list` selector to `.result`. 2. Find all visible entries (change the `.entry-list__item` selector to `.result__item` and change the filter condition: `!entry.classList.contains('hide')`). 3. Get the prev/next element in the array of visible entries to get their IDs from the data-entry-id attribute, no change needed. 4. Modify the anchor element to include the prevId/nextId in the href (change the link selector from `entry-list__link` to `.result__link`).  
  > **username_1**: The other option (#2 in my list) would be to add the selected category IDs to the links instead of adding the prev/next entry IDs directly. This would be even more involved though, especially in terms of server-side code.  
  > **username_0**: these adjustments i already did, this understanding of your code i have ;). but no luck. To add the selected category IDs to the links, this is what i dont get. is this covered in the last part of your code (modifiedUrl)? I tried to edit the {{entry.url)), but no luck  
  > **username_1**: @username_0 No, my sample code follows approach #3. If you want to go with approach #2 instead, you could throw out 90% of the JS code. Just loop through all the entry links and add the selected category IDs to them. Check the part of my code using URLSearchParams on how to add query parameters to existing links. However, then you also have to adjust your backend code to read those parameters and add them to the params for `getNext` / `getPrev`.  
  
  ---
  
  