<p>You're bumping into a Twig gotcha: you can't conditionally extend a template. Either a template extends another template (i.e. it has an <code>{% extends %}</code> tag in it) or it doesn't. It doesn't matter if the <code>{% extends %}</code> statement is inside an <code>{% if %}</code> statement.</p>

<p>The solution is to create an additional layout template – e.g. <code>_ajax.html</code> – and use a <a href="https://en.wikipedia.org/wiki/%3F:" rel="nofollow">ternary operator</a> to have your entry template extend <em>one or the other</em>, before putting the conditional that loads either the content or the call to <code>entryCount.increment</code> inside the <code>{% block content %}</code>. Note that for your purposes, the <code>_ajax.html</code> template can be completely blank, except of course for the <code>{% block content %}{% endblock %}</code>). Also note that since we now need to test if the request is an Ajax request twice, it makes sense to cache the test to a variable <code>isAjax</code>:</p>

<pre><code>{% set isAjax = craft.request.isAjax and not craft.request.isLivePreview %}
{% extends not isAjax ? '_layout' : '_ajax' %}
{% block content %}
    {% if not isAjax %}
        {# CONTENT GOES HERE #}
    {% else %}
        {% do craft.entryCount.increment(entry.id) %}
    {% endif %}
{% endblock %}
</code></pre>

<p>Not very elegant, is it? A better option might be to create a different endpoint for incrementing the counter entirely, negating the need to create an additional layout template and to wrap most of your content in a conditional. To create a dedicated endpoint for incrementing the counter, you can create <a href="https://craftcms.com/docs/routing#dynamic-routes" rel="nofollow">a dynamic route</a>. Make sure the route contains a <code>&lt;number&gt;</code> token, which will hold your entry ID (the route could just be <code>count/&lt;number&gt;</code>, for instance). Have the route point to a new template called <code>_count.html</code> or the like, and put the following in that template:</p>

<pre><code>{% do craft.entryCount.increment(number) %}
</code></pre>

<p>You'll have to expose the current entry's ID to your JavaScript somehow, but that's easily done by setting a data attribute somewhere in your markup – e.g.</p>

<pre><code>&lt;body data-entryid="{{ entry.id }}"&gt;
</code></pre>

<p>Then, you just need to use jQuery or the like to issue a request to <a href="http://yourwebsite.com/count" rel="nofollow">http://yourwebsite.com/count</a>:</p>

<pre><code>$.ajax('/count/'+$('body').data('entryid'));
</code></pre>

<p>Closing thought: So long as you "don't need to actually pickup any data or show it", I'm curious why you couldn't just request the basic template as-is. As long as the template contains the call to <code>entryCount.increment</code> somewhere inside the <code>{% block content %}</code> block, does it really matter if it loads the full layout behind the scenes? Sure, there's a little overhead, but it's way less work and probably doesn't matter that much in the scheme of things.</p>

CC BY-SA 3.0
2016-07-11T20:32:34.243Z
First off, thank you for your suggested solution, I'll dig my face into it in a sec.

I figured it would just be more efficient if it did not load any unnecessary data just to register a view (to explain why. I open a modal with the item's info, instead of loading a new page. But also leave the possibility to share and therefor end up on a single page view of the item.) 

And currently the opening animation lags as the page is loaded through the $.get() I'm pretty sure it wont do this if it does not get an entire page as a respons.
Kitsune
CC BY-SA 3.0
2016-07-11T20:39:20.753Z
Whatever happens serverside shouldn't affect the performance of your front end code and as long as you don't add any callbacks (i.e. `success`, `error`, `complete` etc), the `$.ajax` call won't hog any client side resources at all – in other words, yes, if you only call the `do` statement you will use (marginally) less resources serverside, but it won't have any impact on your animation performance whatsoever.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2016-07-11T20:41:06.153Z
Come to think of it, I'm not sure if `$.get` allows not having a `success` callback, but `$.ajax` definitely does.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2016-07-11T20:42:56.403Z
I'm not expert on that. But if I console.log(data); i see the entire raw HTML. doesn't that load a lot slower than just a little message (from the increase count bit)? I tried with $.ajax too (first attempt.)

What I can say is that it does take a moment to load, I'd rather it would just increase the count through a request alone. Using the $.get() right?
Kitsune
CC BY-SA 3.0
2016-07-11T20:44:48.063Z
Right, but that `console.log` could very well be the reason for the lag by itself :) Just remove the callback entirely. You're not going to use the returned data either way, so you don't need a callback.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2016-07-11T20:48:27.603Z
Got it. I'll try your solution and report back soon. Thanks again Mats!
Kitsune
CC BY-SA 3.0
2016-07-12T21:42:18.493Z
Thanks again Mats. Went with the Route setup. Clean way of doing what I wanted.
Kitsune
CC BY-SA 3.0
2016-07-12T21:43:35.820Z
@Kitsune Awesome, happy it worked out!
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2016-07-11T20:17:12.850Z
2016-07-11T20:41:27.780Z
2016-07-11T20:41:27.780Z
Mats Mikkel Rummelhoff
<p>I can't stand this and have to ask for help again.. Still working on my buddy's website.</p>

<p>I want to increase a entry's counter (using Entry Count plugin)
So for my _entry.html I added an if statement to see if the request is for Ajax or not. If not, show the entire page. If it is only run the counter twig line.</p>

<p>_entry.html</p>

<pre><code>{% if not craft.request.isAjax and not craft.request.isLivePreview %}
    {% extends "_layout" %}
    {% set title = entry.title|t %}

{% block content %}
 {# CONTENT GOES HERE #}
{% endblock %}

{% else %}
    {# ONLY INCREASE THE VIEWS/COUNT #}
    {% do craft.entryCount.increment(entry.id) %}
{% endif %}
</code></pre>

<p>Javascript on main page</p>

<pre><code>$.get($(this).attr('data-url-item'), function(data) {
console.log(data);
});
</code></pre>

<p>Now I don't need to actually pickup any data or show it, so I'm using $.get() currently have the console.log() there so I can see which version of the page I'm getting.</p>

<p>Any help is appreciated.</p>

CC BY-SA 3.0
2016-07-10T19:12:48.773Z
Also, how this currently works is that the direct url works fine. the $.get() gets the same page (entire HTML/resources) instead of the nothing it should get back (but do activate that twig upon load.)
Kitsune
<ajax>
if isAjax not working or not detecting ajax request in template
# if isAjax not working or not detecting ajax request in template

(Asked by: username_0 on 2016-07-10)

I can't stand this and have to ask for help again.. Still working on my buddy's website.
I want to increase a entry's counter (using Entry Count plugin)
So for my _entry.html I added an if statement to see if the request is for Ajax or not. If not, show the entire page. If it is only run the counter twig line.
_entry.html
{% if not craft.request.isAjax and not craft.request.isLivePreview %}
    {% extends "_layout" %}
    {% set title = entry.title|t %}

{% block content %}
 {# CONTENT GOES HERE #}
{% endblock %}

{% else %}
    {# ONLY INCREASE THE VIEWS/COUNT #}
    {% do craft.entryCount.increment(entry.id) %}
{% endif %}

Javascript on main page
$.get($(this).attr('data-url-item'), function(data) {
console.log(data);
});

Now I don't need to actually pickup any data or show it, so I'm using $.get() currently have the console.log() there so I can see which version of the page I'm getting.
Any help is appreciated.

**Tags:** ajax

> **Comments:**
> **username_0**: Also, how this currently works is that the direct url works fine. the $.get() gets the same page (entire HTML/resources) instead of the nothing it should get back (but do activate that twig upon load.)  

---

## 1 answers

### Answer by username_1 on 2016-07-11. Score: 2 | Accepted answer

You're bumping into a Twig gotcha: you can't conditionally extend a template. Either a template extends another template (i.e. it has an {% extends %} tag in it) or it doesn't. It doesn't matter if the {% extends %} statement is inside an {% if %} statement.
The solution is to create an additional layout template – e.g. _ajax.html – and use a ternary operator to have your entry template extend one or the other, before putting the conditional that loads either the content or the call to entryCount.increment inside the {% block content %}. Note that for your purposes, the _ajax.html template can be completely blank, except of course for the {% block content %}{% endblock %}). Also note that since we now need to test if the request is an Ajax request twice, it makes sense to cache the test to a variable isAjax:
{% set isAjax = craft.request.isAjax and not craft.request.isLivePreview %}
{% extends not isAjax ? '_layout' : '_ajax' %}
{% block content %}
    {% if not isAjax %}
        {# CONTENT GOES HERE #}
    {% else %}
        {% do craft.entryCount.increment(entry.id) %}
    {% endif %}
{% endblock %}

Not very elegant, is it? A better option might be to create a different endpoint for incrementing the counter entirely, negating the need to create an additional layout template and to wrap most of your content in a conditional. To create a dedicated endpoint for incrementing the counter, you can create a dynamic route. Make sure the route contains a  token, which will hold your entry ID (the route could just be count/, for instance). Have the route point to a new template called _count.html or the like, and put the following in that template:
{% do craft.entryCount.increment(number) %}

You'll have to expose the current entry's ID to your JavaScript somehow, but that's easily done by setting a data attribute somewhere in your markup – e.g.


Then, you just need to use jQuery or the like to issue a request to http://yourwebsite.com/count:
$.ajax('/count/'+$('body').data('entryid'));

Closing thought: So long as you "don't need to actually pickup any data or show it", I'm curious why you couldn't just request the basic template as-is. As long as the template contains the call to entryCount.increment somewhere inside the {% block content %} block, does it really matter if it loads the full layout behind the scenes? Sure, there's a little overhead, but it's way less work and probably doesn't matter that much in the scheme of things.

> **Comments:**
> **username_0**: First off, thank you for your suggested solution, I'll dig my face into it in a sec.  I figured it would just be more efficient if it did not load any unnecessary data just to register a view (to explain why. I open a modal with the item's info, instead of loading a new page. But also leave the possibility to share and therefor end up on a single page view of the item.)   And currently the opening animation lags as the page is loaded through the $.get() I'm pretty sure it wont do this if it does not get an entire page as a respons.  
> **username_1**: Whatever happens serverside shouldn't affect the performance of your front end code and as long as you don't add any callbacks (i.e. `success`, `error`, `complete` etc), the `$.ajax` call won't hog any client side resources at all – in other words, yes, if you only call the `do` statement you will use (marginally) less resources serverside, but it won't have any impact on your animation performance whatsoever.  
> **username_1**: Come to think of it, I'm not sure if `$.get` allows not having a `success` callback, but `$.ajax` definitely does.  
> **username_0**: I'm not expert on that. But if I console.log(data); i see the entire raw HTML. doesn't that load a lot slower than just a little message (from the increase count bit)? I tried with $.ajax too (first attempt.)  What I can say is that it does take a moment to load, I'd rather it would just increase the count through a request alone. Using the $.get() right?  
> **username_1**: Right, but that `console.log` could very well be the reason for the lag by itself :) Just remove the callback entirely. You're not going to use the returned data either way, so you don't need a callback.  
> **username_0**: Got it. I'll try your solution and report back soon. Thanks again Mats!  
> **username_0**: Thanks again Mats. Went with the Route setup. Clean way of doing what I wanted.  
> **username_1**: @username_0 Awesome, happy it worked out!  

---

