{"id":1796,"date":"2020-07-20T16:51:42","date_gmt":"2020-07-20T09:51:42","guid":{"rendered":"https:\/\/wptips.dev\/?p=1796"},"modified":"2020-07-21T20:37:30","modified_gmt":"2020-07-21T13:37:30","slug":"javascript-rest-api","status":"publish","type":"post","link":"https:\/\/pixelstudio.id\/blog\/javascript-rest-api\/","title":{"rendered":"How to use JavaScript for WordPress REST API (AJAX)"},"content":{"rendered":"\n<p>Have you seen a new section gets loaded without a page refresh?<\/p>\n\n\n\n<p>This is using a JavaScript technique called <strong>AJAX<\/strong> where the client can call API to retrieve data and append it to the current page.<\/p>\n\n\n\n<p>Let&#8217;s learn by creating a &#8220;LOAD MORE&#8221; button to show the next set of posts.<\/p>\n\n\n\n<p style=\"font-size:14px\" class=\"has-background has-light-yellow-background-color\"><strong>Important<\/strong>: This tutorial is only intended to teach you about AJAX and not a good way to create a Load More button. It&#8217;s far better if you create a <a href=\"https:\/\/pixelstudio.id\/blog\/custom-rest-api\/\" target=\"_blank\" rel=\"noreferrer noopener\">custom API endpoint<\/a> and re-use the existing <code>template-parts<\/code> from your theme to render.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lesson #1: Choosing a Library<\/h2>\n\n\n\n<p>Although it&#8217;s possible to do without any library, it&#8217;s easier with one like <a rel=\"noreferrer noopener\" href=\"https:\/\/reactjs.org\/\" target=\"_blank\">React<\/a>, <a rel=\"noreferrer noopener\" href=\"https:\/\/handlebarsjs.com\/\" target=\"_blank\">Handlebars<\/a>, or <a rel=\"noreferrer noopener\" href=\"https:\/\/idangero.us\/template7\/\" target=\"_blank\">Template7<\/a>.<\/p>\n\n\n\n<p><strong>React <\/strong>is the library used in Gutenberg editor. It is powerful yet hard to learn and definitely overkill for a Load More button.<\/p>\n\n\n\n<p>On the other hand, <strong>Handlebars <\/strong>and <strong>Template7 <\/strong>are very simple libraries. They have nearly identical syntaxes but the latter is 4x smaller in size (50KB vs 12KB).<\/p>\n\n\n\n<p>So we decided to use Template7 for this tutorial. <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/nolimits4web\/template7\/tree\/master\/dist\" target=\"_blank\">Download it here<\/a> or use the CDN link at:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/template7\/1.4.1\/template7.min.js<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lesson #2: Create &amp; Render a Template<\/h2>\n\n\n\n<p>The template is written inside <code><strong>&lt;template&gt;<\/strong><\/code> tag:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"html\" class=\"language-html\">&lt;template id=\"template-name\">\n  &lt;p> Hello, my name is {{ firstName }} {{ lastName }} &lt;\/p>\n&lt;\/template><\/code><\/pre>\n\n\n\n<p>If you&#8217;re wondering, that&#8217;s a legit HTML tag specifically used to hold content that will be rendered with JavaScript.<\/p>\n\n\n\n<p>You can render the template by passing in an object like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"javascript\" class=\"language-javascript\">let rawTemplate = document.querySelector('#template-name').innerHTML;\nlet template = Template7.compile( rawTemplate );\n\nlet html = template({\n  firstName: 'John',\n  lastName: 'Doe'\n});\n\n\/\/ the `html` variable contains the rendered template\n\/\/ you can use it to insert anywhere you want<\/code><\/pre>\n\n\n\n<p>Here&#8217;s a CodePen showcasing the snippets above: <\/p>\n\n\n\n<p class=\"codepen\" data-height=\"340\" data-theme-id=\"12982\" data-default-tab=\"js,result\" data-user=\"hrsetyono\" data-slug-hash=\"qBbLBBv\" style=\"height: 340px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\" data-pen-title=\"Template 7 Basic Showcase\">\n  <span>See the Pen <a href=\"https:\/\/codepen.io\/hrsetyono\/pen\/qBbLBBv\">\n  Template 7 Basic Showcase<\/a> by hrsetyono (<a href=\"https:\/\/codepen.io\/hrsetyono\">@hrsetyono<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/span>\n<\/p>\n<script async=\"\" src=\"https:\/\/static.codepen.io\/assets\/embed\/ei.js\"><\/script>\n\n\n\n<h2 class=\"wp-block-heading\">Lesson #3: Conditional and Loop<\/h2>\n\n\n\n<p><strong>CONDITIONAL<\/strong><\/p>\n\n\n\n<p>The conditional in Template7 is limited to checking true or false like below:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"html\" class=\"language-html\">&lt;h4>{{ firstName }} {{ lastName }}&lt;\/h4>\n&lt;p>{{ bio }}&lt;\/p>\n\n{{#if showEmail }}\n  &lt;p>Email: {{ email }}&lt;\/p>\n{{else }}\n  &lt;p>Email is hidden&lt;\/p>\n{{\/if }}<\/code><\/pre>\n\n\n\n<p class=\"codepen\" data-height=\"340\" data-theme-id=\"12982\" data-default-tab=\"js,result\" data-user=\"hrsetyono\" data-slug-hash=\"NWxePqB\" style=\"height: 363px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\" data-pen-title=\"Template 7 - Basic Showcase 02\">\n  <span>See the Pen <a href=\"https:\/\/codepen.io\/hrsetyono\/pen\/NWxePqB\">\n  Template 7 &#8211; Basic Showcase 02<\/a> by hrsetyono (<a href=\"https:\/\/codepen.io\/hrsetyono\">@hrsetyono<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/span>\n<\/p>\n<script async=\"\" src=\"https:\/\/static.codepen.io\/assets\/embed\/ei.js\"><\/script>\n\n\n\n<p><strong>LOOP<\/strong><\/p>\n\n\n\n<p>Let&#8217;s say we have this posts data:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"javascript\" class=\"language-javascript\">[\n  {\n    title: 'Hello World',\n    excerpt: 'Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta debitis quisquam, ullam officiis.',\n    link: 'https:\/\/yoursite.com\/hello-world'\n  },\n\n  {\n    title: 'Second Post',\n    excerpt: 'Voluptatem obcaecati corrupti eius culpa, placeat rem eligendi deserunt earum ut possimus dolores',\n    link: 'https:\/\/yoursite.com\/second-post'\n  },\n]<\/code><\/pre>\n\n\n\n<p>Here&#8217;s the template to loop them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"html\" class=\"language-html\">{{#each this }}\n  &lt;li>\n    &lt;h2> &lt;a href=\"{{ link }}\">\n      {{ title }}\n    &lt;\/a> &lt;\/h2>\n    &lt;p>{{ excerpt }}&lt;\/p>\n  &lt;\/li>\n{{else }}\n  &lt;li>There's no post&lt;\/li>\n{{\/each }}<\/code><\/pre>\n\n\n\n<p class=\"codepen\" data-height=\"340\" data-theme-id=\"12982\" data-default-tab=\"js,result\" data-user=\"hrsetyono\" data-slug-hash=\"yLeGyOr\" style=\"height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\" data-pen-title=\"Template 7 - Basic Showcase 03\">\n  <span>See the Pen <a href=\"https:\/\/codepen.io\/hrsetyono\/pen\/yLeGyOr\">\n  Template 7 &#8211; Basic Showcase 03<\/a> by hrsetyono (<a href=\"https:\/\/codepen.io\/hrsetyono\">@hrsetyono<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/span>\n<\/p>\n<script async=\"\" src=\"https:\/\/static.codepen.io\/assets\/embed\/ei.js\"><\/script>\n\n\n\n<p><code>this<\/code> refers to the current variable. Since we passed in an array, we don&#8217;t have a name to refer the variable, so we use <code>this<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lesson #4: API Helper<\/h2>\n\n\n\n<p>The native API function (called <code>fetch<\/code>) is quite wordy. So it will make your life easier to create these helper functions as a shortcut:<\/p>\n\n\n\n<pre title=\"app.js\" class=\"wp-block-code\"><code lang=\"javascript\" class=\"language-javascript\">const myAPI = {\n  get( endpoint ) {\n    return window.fetch( endpoint, {\n      method: 'GET',\n      headers: { 'Accept': 'application\/json' }\n    } )\n    .then( this._handleError )\n    .then( this._handleContentType )\n    .catch( this._throwError );\n  },\n\n  post( endpoint, body ) {\n    return window.fetch( endpoint, {\n      method: 'POST',\n      headers: { 'content-type': 'application\/json' },\n      body: JSON.stringify( body ),\n    } )\n    .then( this._handleError )\n    .then( this._handleContentType )\n    .catch( this._throwError );\n  },\n\n  _handleError( err ) {\n    return err.ok ? err : Promise.reject( err.statusText )\n  },\n\n  _handleContentType( res ) {\n    const contentType = res.headers.get( 'content-type' );\n    if( contentType &amp;&amp; contentType.includes( 'application\/json' ) ) {\n      return res.json()\n    }\n    return Promise.reject( 'Oops, we haven\\'t got JSON!' )\n  },\n\n  _throwError( err ) {\n    throw new Error( err );\n  }\n}<\/code><\/pre>\n\n\n\n<p>How to use it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"javascript\" class=\"language-javascript\">\/\/ GET request\nmyAPI.get( url ).then( result => {\n  \/\/ do something\n} );\n\n\/\/ POST request\nmyAPI.post( url, data ).then( result => {\n  \/\/ do something\n} );<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lesson #5: Calling for API<\/h2>\n\n\n\n<p>Let&#8217;s try calling the <strong>Posts API<\/strong> of WPTips website and display it. By combining what we have learned, this is quite simple to do:<\/p>\n\n\n\n<p class=\"codepen\" data-height=\"400\" data-theme-id=\"12982\" data-default-tab=\"js\" data-user=\"hrsetyono\" data-slug-hash=\"eYJbmMN\" style=\"height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\" data-pen-title=\"Template 7 - Lesson 05 - API Call\">\n  <span>See the Pen <a href=\"https:\/\/codepen.io\/hrsetyono\/pen\/eYJbmMN\">\n  Template 7 &#8211; Lesson 05 &#8211; API Call<\/a> by hrsetyono (<a href=\"https:\/\/codepen.io\/hrsetyono\">@hrsetyono<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/span>\n<\/p>\n<script async=\"\" src=\"https:\/\/static.codepen.io\/assets\/embed\/ei.js\"><\/script>\n\n\n\n<p>Lastly, we created a <strong>Load More button<\/strong> with click listener and added pagination parameter to the API URL like shown below:<\/p>\n\n\n\n<p class=\"codepen\" data-height=\"400\" data-theme-id=\"12982\" data-default-tab=\"js,result\" data-user=\"hrsetyono\" data-slug-hash=\"PoZXPjb\" style=\"height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\" data-pen-title=\"Template 7 - Lesson 05b - API Call with Load More\">\n  <span>See the Pen <a href=\"https:\/\/codepen.io\/hrsetyono\/pen\/PoZXPjb\">\n  Template 7 &#8211; Lesson 05b &#8211; API Call with Load More<\/a> by hrsetyono (<a href=\"https:\/\/codepen.io\/hrsetyono\">@hrsetyono<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/span>\n<\/p>\n<script async=\"\" src=\"https:\/\/static.codepen.io\/assets\/embed\/ei.js\"><\/script>\n\n\n\n<h2 class=\"wp-block-heading\">Lesson #6: Using it in WordPress<\/h2>\n\n\n\n<p>Enqueue your custom JS and Template7:<\/p>\n\n\n\n<pre title=\"functions.php\" class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_action( 'wp_enqueue_scripts', function() {\n  $js_dir = get_template_directory_uri() . '\/js';\n  \n  wp_enqueue_script( 'my-template', $js_dir . '\/my-template.js', [], '', true );\n  wp_enqueue_script( 'template7', 'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/template7\/1.4.1\/template7.min.js', [], '', true );\n} );<\/code><\/pre>\n\n\n\n<p>Find a way to output the <code>&lt;template&gt;<\/code> tag. For example, we can echo it in footer:<\/p>\n\n\n\n<pre title=\"functions.php\" class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_action( 'wp_footer', function() { ?>\n\n  &lt;template id=\"template-posts\">\n    {{#each this }}\n    &lt;li>\n      &lt;h3> &lt;a href=\"{{ link }}\">\n        {{ title.rendered }}\n        &lt;\/a> &lt;\/h3>\n      &lt;p>{{ excerpt.rendered }}&lt;\/p>\n    &lt;\/li>\n\n    {{else }}\n    &lt;p>There's no post&lt;\/p>\n    {{\/each }}\n  &lt;\/template>\n\n&lt;?php } );<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator is-style-dots\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>You have learned how to do API calls with JavaScript and rendering it using the infamous &#8220;Mustache&#8221; syntax (because the curly brace looks like a mustache).<\/p>\n\n\n\n<p>That should bring you up to speed with the basic of AJAX.<\/p>\n\n\n\n<p>If you are interested to learn more, the first thing you should read next is <a href=\"https:\/\/idangero.us\/template7\/\" target=\"_blank\" rel=\"noreferrer noopener\">Template7 official docs<\/a>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>Thank you for reading. If you have any question, feel free to post it in the comment below \ud83d\ude42<\/p><\/blockquote>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Have you seen a new section gets loaded without a page refresh? This technique is called AJAX and we will learn how to do that<\/p>\n","protected":false},"author":1,"featured_media":1817,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[46,32,31],"class_list":["post-1796","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-frontend","tag-api","tag-javascript","tag-php"],"blocksy_meta":"","_links":{"self":[{"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/posts\/1796","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/comments?post=1796"}],"version-history":[{"count":10,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/posts\/1796\/revisions"}],"predecessor-version":[{"id":1819,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/posts\/1796\/revisions\/1819"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/media\/1817"}],"wp:attachment":[{"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/media?parent=1796"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/categories?post=1796"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pixelstudio.id\/blog\/wp-json\/wp\/v2\/tags?post=1796"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}