Answers.Body: <p>I can think of a couple of simple ways to output an entry's properties on a click event. If there aren't too many of them, you could output the properties that you want as data attributes on the link/button element in your Twig template, then access them from a JS <code>click</code> event handler:</p>
  <pre><code>{# Twig template #}
  &lt;a href=&quot;someUrl&quot;
      class=&quot;myLink&quot;
      data-title=&quot;{{ entry.title }}&quot; 
      data-custom-property=&quot;{{ entry.customProperty }}&quot;&gt;
      Link text
  &lt;/a&gt;
  
  // JavaScript code
  const myLink = document.querySelector('a.myLink');
  myLink.addEventListener('click', function() {
      // Get properties
      const title = myLink.getAttribute('data-title');
      const customProperty = myLink.getAttribute('data-custom-property');
  });
  </code></pre>
  <p>That's probably the simplest method. If you want to access a lot of properties, you could output them into a JavaScript global variable in your Twig template and access them that way, but that can be messy and pollute the global JS scope.</p>
  <p>If you want to get more advanced, the <a href="https://plugins.craftcms.com/element-api" rel="nofollow noreferrer">Element API</a> plugin is the next step. This allows you to create endpoints that you can access via XHR/fetch requests, which return JSON data that you specify. See <a href="https://github.com/craftcms/element-api#setup" rel="nofollow noreferrer">here</a> for an example of how the Element API works.</p>
  <p>Using the Element API, your click event handler could fetch the entry's JSON data and output it dynamically as needed. You'd have something like this in your <code>config/element-api.php</code> config file:</p>
  <pre><code>&lt;?php
  
  use craft\elements\Entry;
  
  return [
      'endpoints' =&gt; [
          'api/entries/all.json' =&gt; function() {
              return [
                  'elementType' =&gt; Entry::class,
                  'criteria' =&gt; ['section' =&gt; 'articles'],
                  'transformer' =&gt; function(Entry $entry) {
                      return [
                          'title' =&gt; $entry-&gt;title,
                          'url' =&gt; $entry-&gt;url,
                          'customProperty' =&gt; $entry-&gt;customProperty,
                      ];
                  },
              ];
          },
          'api/entries/&lt;entryId:\d+&gt;.json' =&gt; function($entryId) {
              return [
                  'elementType' =&gt; Entry::class,
                  'criteria' =&gt; ['id' =&gt; $entryId],
                  'one' =&gt; true,
                  'transformer' =&gt; function(Entry $entry) {
                      return [
                          'title' =&gt; $entry-&gt;title,
                          'url' =&gt; $entry-&gt;url,
                          'customProperty' =&gt; $entry-&gt;customProperty,
                      ];
                  },
              ];
          },
      ]
  ];
  </code></pre>
  <p>Accessing <code>https://my-site-url/api/entries/all.json</code> would return a JSON object with an array of all the entries, and accessing <code>https://my-site-url/api/entries/123456.json</code> would return a JSON object with the properties for the Entry with an ID of 123456.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-03-05T09:29:27.200Z
Answers.LastActivityDate: 2021-03-05T09:29:27.200Z
Answers.UserDisplayName: Martin Spain
Answers.Body: <p>You don't need the Element API, or a custom plugin, or GraphQL, or Sprig, for this. Simply set up a template and then call it via ajax. The template can return a chunk of html and use POST or GET parameters to decide what it needs to fetch. If you prefer, the template could just as easily return a chunk of JSON or XML or plain text or whatever else you want. You don't mention if you're using a JS framework, but for simplicity here's a jQuery way using <a href="https://api.jquery.com/load/" rel="nofollow noreferrer">load</a>:</p>
  <pre class="lang-html prettyprint-override"><code>/// main template:
      
  &lt;button
      type=&quot;button&quot;
      data-url=&quot;/ajax-load-entry?id=123&quot;
      data-element-id=&quot;123&quot;
      class=&quot;js-ajaxLoad&quot;
  &gt;
      Load Entry #123
  &lt;/button&gt;
  
  &lt;div class=&quot;ajax-result-container-for-123&quot;&gt;&lt;/div&gt;
  
  &lt;script&gt;
      $('.js-ajaxLoad').click(function(){
          var url = $(this).data('url');
          var elementId = $(this).data('elementId');
          $('.ajax-result-container-for-' + elementId).load(url);
      });
  &lt;/script&gt;
  
  /// templates/ajax-load-entry.twig template:
  
  {% if craft.app.request.getParam('id') %}
      {% set entry = craft.entries.id(craft.app.request.param('id')).one() %}
      {% if entry %}
          &lt;h1&gt;{{ entry.title }}&lt;/h1&gt;
          {{ entry.body ?? null }}
      {% endif %}
  {% endif %}
  </code></pre>
  <p>I appreciate jQuery's not very fashionable these days, but the same concept could very easily be translated into a native <code>fetch</code> call if you don't need IE11 support (or if you're transpiling). Something like this should work in native JS:</p>
  <pre class="lang-html prettyprint-override"><code>&lt;script&gt;
      document.querySelector('.js-ajaxLoad').addEventListener('click', function(){
          let url = this.dataset.url;
          let elementId = this.dataset.elementId;
          fetch(url).then(function(response) {
              return response.text();
          }).then(function (html) {
              document.querySelector('.ajax-result-container-for-' + elementId).innerHTML = html;
          });
      });
  &lt;/script&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-03-05T11:26:10.117Z
Answers.Text: If I could put both as answers - I would. This is a great example of utilising Craft's own power.
Answers.UserDisplayName: JMKelley
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-04-28T02:49:19.020Z
Answers.Text: Thank you! This works perfectly!
Answers.UserDisplayName: mateostabio
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-03-05T10:14:13.987Z
Answers.LastActivityDate: 2024-01-23T15:03:11.760Z
Answers.LastEditDate: 2024-01-23T15:03:11.760Z
Answers.UserDisplayName: James Smith
Body: <p>I'm simply looking to <code>onClick</code> load an entries content via Ajax. Thought I see a lot of mixed answers here on SO, some referring to Element API, Creating a Plugin and GraphQL. Is there a simple way to just get an entries properties on click e.g. title?</p>
  
Tags: <templating>
Title: Load Entry via Ajax
ThreadText: # Load Entry via Ajax
  
  (Asked by: username_0 on 2021-03-04)
  
  I'm simply looking to `onClick` load an entries content via Ajax. Thought I see a lot of mixed answers here on SO, some referring to Element API, Creating a Plugin and GraphQL. Is there a simple way to just get an entries properties on click e.g. title?
  
  **Tags:** templating
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2021-03-05. Score: 2 | Accepted answer
  
  I can think of a couple of simple ways to output an entry's properties on a click event. If there aren't too many of them, you could output the properties that you want as data attributes on the link/button element in your Twig template, then access them from a JS `click` event handler:
  
  ```
  {# Twig template #}
  <a href="someUrl"
      class="myLink"
      data-title="{{ entry.title }}" 
      data-custom-property="{{ entry.customProperty }}">
      Link text
  </a>
  
  // JavaScript code
  const myLink = document.querySelector('a.myLink');
  myLink.addEventListener('click', function() {
      // Get properties
      const title = myLink.getAttribute('data-title');
      const customProperty = myLink.getAttribute('data-custom-property');
  });
  
  ```
  
  That's probably the simplest method. If you want to access a lot of properties, you could output them into a JavaScript global variable in your Twig template and access them that way, but that can be messy and pollute the global JS scope.
  
  If you want to get more advanced, the [Element API](https://plugins.craftcms.com/element-api) plugin is the next step. This allows you to create endpoints that you can access via XHR/fetch requests, which return JSON data that you specify. See [here](https://github.com/craftcms/element-api#setup) for an example of how the Element API works.
  
  Using the Element API, your click event handler could fetch the entry's JSON data and output it dynamically as needed. You'd have something like this in your `config/element-api.php` config file:
  
  ```
  <?php
  
  use craft\elements\Entry;
  
  return [
      'endpoints' => [
          'api/entries/all.json' => function() {
              return [
                  'elementType' => Entry::class,
                  'criteria' => ['section' => 'articles'],
                  'transformer' => function(Entry $entry) {
                      return [
                          'title' => $entry->title,
                          'url' => $entry->url,
                          'customProperty' => $entry->customProperty,
                      ];
                  },
              ];
          },
          'api/entries/<entryId:\d+>.json' => function($entryId) {
              return [
                  'elementType' => Entry::class,
                  'criteria' => ['id' => $entryId],
                  'one' => true,
                  'transformer' => function(Entry $entry) {
                      return [
                          'title' => $entry->title,
                          'url' => $entry->url,
                          'customProperty' => $entry->customProperty,
                      ];
                  },
              ];
          },
      ]
  ];
  
  ```
  
  Accessing `https://my-site-url/api/entries/all.json` would return a JSON object with an array of all the entries, and accessing `https://my-site-url/api/entries/123456.json` would return a JSON object with the properties for the Entry with an ID of 123456.
  
  
  ---
  
  ### Answer by username_2 on 2021-03-05. Score: 6
  
  You don't need the Element API, or a custom plugin, or GraphQL, or Sprig, for this. Simply set up a template and then call it via ajax. The template can return a chunk of html and use POST or GET parameters to decide what it needs to fetch. If you prefer, the template could just as easily return a chunk of JSON or XML or plain text or whatever else you want. You don't mention if you're using a JS framework, but for simplicity here's a jQuery way using [load](https://api.jquery.com/load/):
  
  ```html
  /// main template:
      
  <button
      type="button"
      data-url="/ajax-load-entry?id=123"
      data-element-id="123"
      class="js-ajaxLoad"
  >
      Load Entry #123
  </button>
  
  <div class="ajax-result-container-for-123"></div>
  
  <script>
      $('.js-ajaxLoad').click(function(){
          var url = $(this).data('url');
          var elementId = $(this).data('elementId');
          $('.ajax-result-container-for-' + elementId).load(url);
      });
  </script>
  
  /// templates/ajax-load-entry.twig template:
  
  {% if craft.app.request.getParam('id') %}
      {% set entry = craft.entries.id(craft.app.request.param('id')).one() %}
      {% if entry %}
          <h1>{{ entry.title }}</h1>
          {{ entry.body ?? null }}
      {% endif %}
  {% endif %}
  
  ```
  
  I appreciate jQuery's not very fashionable these days, but the same concept could very easily be translated into a native `fetch` call if you don't need IE11 support (or if you're transpiling). Something like this should work in native JS:
  
  ```html
  <script>
      document.querySelector('.js-ajaxLoad').addEventListener('click', function(){
          let url = this.dataset.url;
          let elementId = this.dataset.elementId;
          fetch(url).then(function(response) {
              return response.text();
          }).then(function (html) {
              document.querySelector('.ajax-result-container-for-' + elementId).innerHTML = html;
          });
      });
  </script>
  
  ```
  
  > **Comments:**
  > **username_0**: If I could put both as answers - I would. This is a great example of utilising Craft's own power.  
  > **username_3**: Thank you! This works perfectly!  
  
  ---
  
  