<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Alpine JS]]></title><description><![CDATA[Content articles for AlpineJS (https://alpinejs.dev) - currently using alpinejs@3.15.11]]></description><link>https://alpinejs.in</link><generator>RSS for Node</generator><lastBuildDate>Tue, 08 Sep 2026 01:05:17 GMT</lastBuildDate><atom:link href="https://alpinejs.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Styling the NumberFormat in JavaScript]]></title><description><![CDATA[If you ever wanted to display a number (amount) in Indian currency format and you have the number in a template variable as total like {{ total }}, then here’s a quick way to go using AlpineJS’s x-text to replace the server-side rendered content.
<td...]]></description><link>https://alpinejs.in/styling-the-numberformat-in-javascript</link><guid isPermaLink="true">https://alpinejs.in/styling-the-numberformat-in-javascript</guid><category><![CDATA[indian currency]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[alpinejs]]></category><category><![CDATA[Intl.NumberFormat]]></category><category><![CDATA[currency]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Wed, 29 Jan 2025 08:32:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738213438699/b7f18f7a-c6a9-4d56-8159-e24dae41062a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you ever wanted to display a number (amount) in Indian currency format and you have the number in a template variable as total like <code>{{ total }}</code>, then here’s a quick way to go using AlpineJS’s <code>x-text</code> to replace the server-side rendered content.</p>
<pre><code class="lang-javascript">&lt;td x-text=<span class="hljs-string">"new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR' }).format({{ total }})"</span>&gt;
    ₹{{ total }}
&lt;/td&gt;
</code></pre>
<p><code>NumberFormat</code> has been supported on all browsers for a long time now.</p>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat</a></p>
]]></content:encoded></item><item><title><![CDATA[Using getters and setters Part 3]]></title><description><![CDATA[Here is the final Part 3 post on getters and setters. This is more refined and considered the goto method.
https://gist.github.com/anjanesh/18630fc3f7b1684569fc6ad34c45a883 
Here, the USD price is pre-defined as usual as price_USD.
The key takeaway i...]]></description><link>https://alpinejs.in/using-getters-and-setters-part-3</link><guid isPermaLink="true">https://alpinejs.in/using-getters-and-setters-part-3</guid><category><![CDATA[getter and setter]]></category><category><![CDATA[alpinejs]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Objects]]></category><category><![CDATA[@property]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Sat, 24 Aug 2024 06:28:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724480747948/cb24e8d8-6dcc-4723-80fb-e7bc918d811d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here is the final Part 3 post on getters and setters. This is more refined and considered the goto method.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="18630fc3f7b1684569fc6ad34c45a883"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/anjanesh/18630fc3f7b1684569fc6ad34c45a883" class="embed-card">https://gist.github.com/anjanesh/18630fc3f7b1684569fc6ad34c45a883</a></div><p> </p>
<p>Here, the USD price is pre-defined as usual as <code>price_USD</code>.</p>
<p>The key takeaway is in this line :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> addINRPrice = <span class="hljs-function">(<span class="hljs-params">product</span>) =&gt;</span> <span class="hljs-built_in">Object</span>.defineProperty(product, <span class="hljs-string">'price_INR'</span>, INRPriceConverter);
</code></pre>
<p><code>price_INR</code> is defined as a property in the <code>products</code> array of objects by setting it in <code>Object.defineProperty</code>. As you can see, there are 3 arguments to this :</p>
<ol>
<li><p>the <code>product</code>, which is the parameter in <code>addINRPrice</code> method.</p>
</li>
<li><p>The other property <code>price_INR</code> which we had declared in the <code>products</code> array explicitly in the first two parts of this blog series, is now dynamically added.</p>
</li>
<li><p>The method that is used to set and get the dynamically added property <code>price_INR</code>.</p>
</li>
</ol>
<p><code>this.products.map(addINRPrice);</code> adds the <code>price_INR</code> property to each of the objects in the <code>products</code> array.</p>
<p>In AlpineJS store's <code>init()</code> method which does some initialisation, a method <code>INRPriceConverter</code> is defined that has a setter and a getter to convert / return USD or INR values.</p>
<p>Let's see what the setter and getter in <code>INRPriceConverter</code> does.</p>
<p>The getter is straight-forward - <code>return this.price_USD * 83;</code> returns the INR value when the USD value is multiplied by 83.</p>
<p>Now the setter which has a parameter <code>val</code> in <code>this.price_USD = val / 83;</code> - here, <code>val</code> is <code>price_INR</code> (that's added dynamically) and calculated to it's USD value.</p>
<p>Demo : <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/alpine-auto-update-variable-method-2.html">https://anjanesh.s3.amazonaws.com/demo/alpine/alpine-auto-update-variable-method-2.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Image PopUp / Photo Gallery using PhotoSwipe]]></title><description><![CDATA[I think one of the most searched query for a jquery plugin was / is that of an image popup, photo gallery etc.
It's now almost a decade since ES6 (2015) - Say GoodBye to jQuery and welcome a Ukranian's PhotoSwipe JavaScript plugin.
Captions is achiev...]]></description><link>https://alpinejs.in/image-popup-photo-gallery-using-photoswipe</link><guid isPermaLink="true">https://alpinejs.in/image-popup-photo-gallery-using-photoswipe</guid><category><![CDATA[photo-gallery]]></category><category><![CDATA[image-popup]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[screenshots]]></category><category><![CDATA[alpinejs]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Thu, 04 Jul 2024 11:27:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1720061668727/9123e59b-848b-49c5-ad04-24adfcfe0441.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I think one of the most searched query for a jquery plugin was / is that of an image popup, photo gallery etc.</p>
<p>It's now almost a decade since ES6 (2015) - Say GoodBye to jQuery and welcome a Ukranian's <a target="_blank" href="https://photoswipe.com/">PhotoSwipe</a> JavaScript plugin.</p>
<p>Captions is achieved using a <a target="_blank" href="https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin">Dynamic caption plugin for PhotoSwipe v5</a>.</p>
<p>The preferred way to load the JavaScript plugin is via a "module" remotely.</p>
<p>Using <code>&lt;script type="module"&gt;</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> PhotoSwipeLightbox <span class="hljs-keyword">from</span> <span class="hljs-string">'https://unpkg.com/photoswipe@5.4.4/dist/photoswipe-lightbox.esm.js'</span>;
</code></pre>
<p>And similarly for the caption plugin :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> PhotoSwipeDynamicCaption <span class="hljs-keyword">from</span> <span class="hljs-string">'https://unpkg.com/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.esm.js'</span>;
</code></pre>
<p>Then we initialise a variable to a <code>new</code> object using regular vanilla JavaScript.</p>
<p>We use AlpineJS to either loop through an array of objects containing the photo details like links and captions <strong>or</strong><a target="_blank" href="https://alpinejs.dev/directives/for">1 through a count</a> and reference the index for each image using <code>:href</code>, <code>:src</code> and <code>:alt</code> (for the caption) like this :</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"i in 18"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">:href</span>=<span class="hljs-string">"'https://planpros.s3.amazonaws.com/images/' + i + 's.webp'"</span>
      <span class="hljs-attr">data-pswp-width</span>=<span class="hljs-string">"1292"</span>
      <span class="hljs-attr">data-pswp-height</span>=<span class="hljs-string">"1225"</span>
      <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"'https://planpros.s3.amazonaws.com/images/' + i + 's.webp'"</span> <span class="hljs-attr">:alt</span>=<span class="hljs-string">"'screenshot demo ' + i"</span> /&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
</code></pre>
<p>In case you're wondering why the colon (:) before <code>href</code>, <code>src</code> and <code>alt</code>, its because we're wanting these attributes to be parsed as JavaScript code which AlpineJS would do it for us. This is the crux of AlpineJS. For example <code>&lt;span :text="'Hello' + ' World'"&gt;&lt;/span&gt;</code> would concatenate the strings <strong>Hello</strong> and <strong>World</strong> and assign the span's text to <strong>Hello World</strong>. Same can be applied to JavaScript variables.</p>
<p>Here's the full source code :</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">dir</span>=<span class="hljs-string">"ltr"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"Content-Type"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"text/html;charset=utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Photoswipe + AlpineJS<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span>  <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://unpkg.com/photoswipe@5.2.2/dist/photoswipe.css"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://unpkg.com/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center text-2xl text-[#022350] md:text-[44px] md:leading-normal"</span>&gt;</span>Here's Exactly What You'll See in the PlanPros Members Area<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4 pswp-gallery"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"gallery-screenshots"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"i in 18"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">:href</span>=<span class="hljs-string">"'https://planpros.s3.amazonaws.com/images/' + i + 's.webp'"</span>
               <span class="hljs-attr">data-pswp-width</span>=<span class="hljs-string">"1292"</span>
               <span class="hljs-attr">data-pswp-height</span>=<span class="hljs-string">"1225"</span>
               <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"'https://planpros.s3.amazonaws.com/images/' + i + 's.webp'"</span> <span class="hljs-attr">:alt</span>=<span class="hljs-string">"'screenshot demo ' + i"</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>            
        <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">import</span> PhotoSwipeLightbox <span class="hljs-keyword">from</span> <span class="hljs-string">'https://unpkg.com/photoswipe@5.4.4/dist/photoswipe-lightbox.esm.js'</span>;
<span class="hljs-keyword">import</span> PhotoSwipeDynamicCaption <span class="hljs-keyword">from</span> <span class="hljs-string">'https://unpkg.com/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.esm.js'</span>;

<span class="hljs-keyword">const</span> lightbox = <span class="hljs-keyword">new</span> PhotoSwipeLightbox({
    <span class="hljs-attr">gallery</span>: <span class="hljs-string">'#gallery-screenshots'</span>,
    <span class="hljs-attr">children</span>: <span class="hljs-string">'a'</span>,
    <span class="hljs-attr">pswpModule</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'https://unpkg.com/photoswipe@5.4.4/dist/photoswipe.esm.js'</span>),
});

<span class="hljs-comment">// https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin</span>
<span class="hljs-keyword">const</span> captionPlugin = <span class="hljs-keyword">new</span> PhotoSwipeDynamicCaption(lightbox, {
  <span class="hljs-comment">// Plugins options, for example:</span>
  <span class="hljs-attr">type</span>: <span class="hljs-string">'auto'</span>,
});

lightbox.init();
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.14.1/dist/cdn.min.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Gist : <a target="_blank" href="https://gist.github.com/anjanesh/bc46a327f830e7e717271032d5b6b60a">https://gist.github.com/anjanesh/bc46a327f830e7e717271032d5b6b60a</a></p>
<p>Demo : <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/photoswipe.html">https://anjanesh.s3.amazonaws.com/demo/alpine/photoswipe.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Using getters and setters Part 2]]></title><description><![CDATA[This is second part in the series to make use of getters and setters in an AlpineJS object, that converts INR to USD.
Well, only a setter has been used here where a function call is made to the setter priceInINR when the textbox of the USD value chan...]]></description><link>https://alpinejs.in/using-getters-and-setters-part-2</link><guid isPermaLink="true">https://alpinejs.in/using-getters-and-setters-part-2</guid><category><![CDATA[getter and setter]]></category><category><![CDATA[alpinejs]]></category><category><![CDATA[currency-converter]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[FIND]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Sat, 17 Feb 2024 04:30:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1708144130572/fcc3b805-643e-4ef6-8506-be97d7af85b3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is second part in the series to make use of getters and setters in an AlpineJS object, that converts INR to USD.</p>
<p>Well, only a <strong>setter</strong> has been used here where a function call is made to the setter <code>priceInINR</code> when the textbox of the USD value changes. The setter changes the value of the product's (which is an argument to <code>priceInINR</code>) <code>price_INR</code> value.</p>
<p><code>x-on:input="$</code><a target="_blank" href="http://store.global"><code>store.global</code></a><code>_data.priceInINR = product"</code></p>
<p>And the setter :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">set</span> <span class="hljs-title">priceInINR</span>(<span class="hljs-params">p</span>)
{            
    <span class="hljs-keyword">const</span> product = <span class="hljs-built_in">this</span>.products.find(<span class="hljs-function"><span class="hljs-params">product</span> =&gt;</span> product.name === p.name);
    product.price_INR = p.price_USD * <span class="hljs-number">83</span>;
},
</code></pre>
<p>Here's the full source code.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="2563f0155a4e303dcd39aa9d3c4e2c7f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/anjanesh/2563f0155a4e303dcd39aa9d3c4e2c7f" class="embed-card">https://gist.github.com/anjanesh/2563f0155a4e303dcd39aa9d3c4e2c7f</a></div><p> </p>
<p>PS: 1 USD = 83 INR as of 17th February 2024.</p>
<p>Here's a more interactive example / demo : <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/alpine-auto-update-variable-method-1.html">https://anjanesh.s3.amazonaws.com/demo/alpine/alpine-auto-update-variable-method-1.html</a></p>
]]></content:encoded></item><item><title><![CDATA[How to access AlpineJS Data variable outside scope]]></title><description><![CDATA[This is actually revealing a one-liner solution because Rahul Rajput of rajputrahul.com has already posted a good article and example of how to access a AlpineJS variable outside of its scope at https://www.rajputrahul.com/access-alpinejs-variable-ou...]]></description><link>https://alpinejs.in/access-alpinejs-variable-outside-scope</link><guid isPermaLink="true">https://alpinejs.in/access-alpinejs-variable-outside-scope</guid><category><![CDATA[alpinejs]]></category><category><![CDATA[Scope]]></category><category><![CDATA[variables]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Fri, 19 Jan 2024 12:25:15 GMT</pubDate><content:encoded><![CDATA[<p>This is actually revealing a one-liner solution because Rahul Rajput of <a target="_blank" href="http://rajputrahul.com">rajputrahul.com</a> has already posted a good article and example of how to access a AlpineJS variable outside of its scope at <a target="_blank" href="https://www.rajputrahul.com/access-alpinejs-variable-outside-scope/">https://www.rajputrahul.com/access-alpinejs-variable-outside-scope/</a> - but this solution is valid for AlpineJS 2.x only - in version 3.x there is a change in the way its accessed.</p>
<p>In AlpineJS 3.x (while adding <a target="_blank" href="https://unpkg.com/alpinejs@3.13.3/dist/cdn.min.js">https://unpkg.com/alpinejs@3.13.3/dist/cdn.min.js</a> in the script tag to load AlpineJS) :</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'modalBox'</span>)._x_dataStack[<span class="hljs-number">0</span>].open = <span class="hljs-literal">false</span>;
</code></pre>
<p>Full Source Code :</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>How to access AlpineJS Data variable outside scope<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.13.3/dist/cdn.min.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>Example one<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{open: false}"</span> @<span class="hljs-attr">keydown.escape</span>=<span class="hljs-string">"open=false"</span> <span class="hljs-attr">x-clock</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-8 py-8 align-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"open=!open"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-3 py-1 border shadow-md bg-indigo-500 text-white"</span>&gt;</span>Toggle button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"open"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"modal"</span>&gt;</span>
                This is modal text.  
                <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"open=false"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-3 py-1 border shadow-md bg-red-500 text-white"</span>&gt;</span>Close Me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>Example two<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"modalBox"</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{open: false}"</span> @<span class="hljs-attr">keydown.escape</span>=<span class="hljs-string">"open=false"</span> <span class="hljs-attr">x-clock</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-8 py-8 align-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"open=!open"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-3 py-1 border shadow-md bg-indigo-500 text-white"</span>&gt;</span>Toggle button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"open"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"modal"</span>&gt;</span>
                This is modal text.  
                <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"open=false"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-3 py-1 border shadow-md bg-red-500 text-white"</span>&gt;</span>Close Me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"hideBox()"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-3 py-1 border shadow-md bg-red-500 text-white"</span>&gt;</span>Toggle button (Outside Scope)<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
        <span class="hljs-built_in">window</span>.hideBox = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
            <span class="hljs-comment">// document.getElementById('modalBox').__x.$data.open = false;</span>
            <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'modalBox'</span>)._x_dataStack[<span class="hljs-number">0</span>].open = <span class="hljs-literal">false</span>;
        }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Using AJAX to load an image in the background]]></title><description><![CDATA[Ever tried loading an image using AJAX/fetch?
Here's a super simple example with AlpineJS parsing an IMG's src value as JavaScript. It can't get simpler than this.
<div x-data="{}">
    <img :src="await(await fetch('https://domain.com/myImage.jpg'))....]]></description><link>https://alpinejs.in/using-ajax-to-load-an-image-in-the-background</link><guid isPermaLink="true">https://alpinejs.in/using-ajax-to-load-an-image-in-the-background</guid><category><![CDATA[Ajax]]></category><category><![CDATA[fetch]]></category><category><![CDATA[fetch API]]></category><category><![CDATA[alpinejs]]></category><category><![CDATA[background tasks]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Wed, 22 Nov 2023 07:07:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1700669847980/278c4df7-1d57-4632-b497-c4e3e17afc60.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever tried loading an image using AJAX/fetch?</p>
<p>Here's a super simple example with AlpineJS parsing an IMG's src value as JavaScript. It can't get simpler than this.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"await(await fetch('https://domain.com/myImage.jpg')).url"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>You'll have to add cors origin like the way it's done at <a target="_blank" href="http://bunny.net">bunny.net</a> - <a target="_blank" href="https://share.getcloudapp.com/bLuARKwx">https://share.getcloudapp.com/bLuARKwx</a></p>
<p>Here's a full source code :</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>    
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Using AJAX to load an image in the background<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.13.2/dist/cdn.min.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{}"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"await(await fetch('https://anjanesh.b-cdn.net/island.jpg')).url"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Note the <strong>.url</strong> and the end of the closing <code>await</code>.</p>
<p><em>the .url is used to get the URL of the response obtained from the fetch operation, and it's accessed using await because fetch returns a promise.</em></p>
]]></content:encoded></item><item><title><![CDATA[Using ENTER for submit and SHIFT+ENTER for multi-line chat]]></title><description><![CDATA[If you've noticed on LinkedIn messaging when you chat with someone, you hit the ENTER key to send the message across and SHIFT+ENTER to enter a new line in the chat box. Most people aren't used to SHIFT+ENTER to go to the next line though.
This is pr...]]></description><link>https://alpinejs.in/using-enter-for-submit-and-shiftenter-for-multi-line-chat</link><guid isPermaLink="true">https://alpinejs.in/using-enter-for-submit-and-shiftenter-for-multi-line-chat</guid><category><![CDATA[alpinejs]]></category><category><![CDATA[textarea]]></category><category><![CDATA[Chat]]></category><category><![CDATA[enter key]]></category><category><![CDATA[shift key]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Wed, 01 Nov 2023 02:29:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698805644327/ddb2fccc-f10f-462a-85d7-41bd90e4c5a4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've noticed on LinkedIn messaging when you chat with someone, you hit the ENTER key to send the message across and SHIFT+ENTER to enter a new line in the chat box. Most people aren't used to SHIFT+ENTER to go to the next line though.</p>
<p>This is pretty simple to replicate using AlpineJS. We listen to <code>@keydown.shift</code> and <code>@keyup.shift</code> where keyup / keydown are the keys that are pressed down or up respectively and <code>.shift</code> is for listening specifically for the SHIFT key.</p>
<pre><code class="lang-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
        @<span class="hljs-attr">keyup.enter</span>=<span class="hljs-string">"
        if (!shiftPressed)
        {
            chats.push($event.target.value);
            $event.target.value = '';
        }
        "</span>
        @<span class="hljs-attr">keydown.shift</span>=<span class="hljs-string">"shiftPressed = true"</span>
        @<span class="hljs-attr">keyup.shift</span>=<span class="hljs-string">"shiftPressed = false"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"type your message here... and hit enter - hit SHIFT+ENTER to enter a new line"</span>
        <span class="hljs-attr">rows</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">cols</span>=<span class="hljs-string">"50"</span>
        &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
</code></pre>
<p>Using <code>x-html</code> is dangerous but newlines in <code>textarea</code> should be converted to HTML.</p>
<p>Here's the complete code.</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>AlpineJS Chat with Shift Enter<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{
    shiftPressed: false,
    chats: []
}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"chat in chats"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-html</span>=<span class="hljs-string">"chat"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">hr</span>/&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
        @<span class="hljs-attr">keyup.enter</span>=<span class="hljs-string">"
        if (!shiftPressed)
        {
            chats.push($event.target.value.replace('\n', '&lt;br/&gt;'));
            $event.target.value = '';
        }
        "</span>
        @<span class="hljs-attr">keydown.shift</span>=<span class="hljs-string">"shiftPressed = true"</span>
        @<span class="hljs-attr">keyup.shift</span>=<span class="hljs-string">"shiftPressed = false"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"type your message here... and hit enter - hit SHIFT+ENTER to enter a new line"</span>
        <span class="hljs-attr">rows</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">cols</span>=<span class="hljs-string">"50"</span>
        &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.13.2/dist/cdn.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Demo : <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/shift-enter.html">https://anjanesh.s3.amazonaws.com/demo/alpine/shift-enter.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Using getters and setters]]></title><description><![CDATA[This is going to be a 3 part series on using getters and setters in AlpineJS.
I knew about set and get in JavaScript which are commonly known as setters and getters but I had never used them in a real case scenario until now. I agree, I am pretty lat...]]></description><link>https://alpinejs.in/using-getters-and-setters</link><guid isPermaLink="true">https://alpinejs.in/using-getters-and-setters</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[alpinejs]]></category><category><![CDATA[getter and setter]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Mon, 16 Oct 2023 02:39:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697423921765/d61903d4-dc43-4c90-bd09-5d9578830e6f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is going to be a 3 part series on using getters and setters in AlpineJS.</p>
<p>I knew about <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set">set</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get">get</a> in JavaScript which are commonly known as setters and getters but I had never used them in a real case scenario until now. I agree, I am pretty late to implementing these, considering these have been available since Chrome 1.0 and Firefox 1.5.</p>
<p>Here is an example of a basic example of using get and set in an AlpineJS global store object.</p>
<p>Let's say you have a product for which you want to show the price in INR (Indian Rupee ₹) and also in US dollars.</p>
<p>Normally we set the price in USD and convert it into INR using a factor of 83 (as of now 1 USD = 83 INR approximately).</p>
<p>So if we set the price of the product as 50 USD, then the price in INR should automatically be converted to 50 x 83 = 4150 INR.</p>
<p>The idea is to set another variable to a converted value when one variable gets changed.</p>
<p>So basically, if we have 2 variables, <code>x</code> and <code>y</code>, <code>y</code> should auto-update when <code>x</code> gets modified.</p>
<p>This will work only if both <code>x</code> and <code>y</code> are defined in an object.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="757c7e763653ac8be6b923b39f4a5d0f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/anjanesh/757c7e763653ac8be6b923b39f4a5d0f" class="embed-card">https://gist.github.com/anjanesh/757c7e763653ac8be6b923b39f4a5d0f</a></div><p> </p>
<p>Demo: <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/alpine-auto-update-variable.html">https://anjanesh.s3.amazonaws.com/demo/alpine/alpine-auto-update-variable.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Update State Variables Automatically]]></title><description><![CDATA[AlpineJS has a global state management system through its global variable named store.
We can store a variable named total for a page loaded in the browser like this :
document.addEventListener('alpine:init', () =>
{
    Alpine.store('global_data',
 ...]]></description><link>https://alpinejs.in/update-state-variables-automatically</link><guid isPermaLink="true">https://alpinejs.in/update-state-variables-automatically</guid><category><![CDATA[event listener ]]></category><category><![CDATA[alpinejs]]></category><category><![CDATA[State Management ]]></category><category><![CDATA[global-store]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Fri, 11 Aug 2023 03:42:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691725304663/8d9a0fd4-2bc4-482e-b3aa-8205e35a6de0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AlpineJS has a global state management system through its global variable named <a target="_blank" href="https://alpinejs.dev/globals/alpine-store">store</a>.</p>
<p>We can store a variable named <code>total</code> for a page loaded in the browser like this :</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'alpine:init'</span>, <span class="hljs-function">() =&gt;</span>
{
    Alpine.store(<span class="hljs-string">'global_data'</span>,
    {
        <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
    });
});
</code></pre>
<p>(Note: This is <strong>not</strong> <code>localStorage</code>, so the store variable will be reset once you navigate to another page)</p>
<p>If you're looking to assign and update a variable stored in <code>$store</code> with change in input elements' values, you don't need to attach event listeners to the respective input elements at all.</p>
<p>Let's have 2 input elements, one for the <strong>quantity</strong> (text field) and one for the <strong>size</strong> of the product (select), where each of the 3 sizes has pre-defined prices.</p>
<p>So for the quantity we can bind the value of the input to a local AlpineJS variable like <code>&lt;input x-model="quantity"&gt;</code> and a <code>&lt;select x-model="price"&gt;</code></p>
<p>And have a total assigned and displayed as :</p>
<pre><code class="lang-xml">x-text="$store.global_data.total = calcTotal(quantity, price)"
</code></pre>
<p>Here is the entire code :</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span> /&gt;</span>    
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>AlpineJS onchange update store variable<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
<span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'alpine:init'</span>, <span class="hljs-function">() =&gt;</span>
{
    Alpine.store(<span class="hljs-string">'global_data'</span>,
    {
        <span class="hljs-attr">total</span>: <span class="hljs-number">0</span>,
    });
});

<span class="hljs-keyword">let</span> calcTotal = <span class="hljs-function">(<span class="hljs-params">quantity, price</span>) =&gt;</span>
{
    <span class="hljs-keyword">return</span> quantity * price;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ quantity:0, price:0 }"</span>&gt;</span>
    Quantity : <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"quantity"</span>/&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"price"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"0"</span>&gt;</span>Select Size<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"150"</span>&gt;</span>Small ($150)<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"360"</span>&gt;</span>Medium ($360)<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"890"</span>&gt;</span>Large ($890)<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>    
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Total : <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"$store.global_data.total = calcTotal(quantity, price)"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.12.3/dist/cdn.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Retrieving AlpineJS data in a global function]]></title><description><![CDATA[I have a form coupled with AlpineJS.
<form
x-data="{ first_name: '', last_name: '' }"
method="POST"
@submit.prevent="submitForm"
>

I want the x-data details, first_name and last_name to be available in a global function.
One option is to retrieve th...]]></description><link>https://alpinejs.in/retrieving-alpinejs-data-in-a-global-function</link><guid isPermaLink="true">https://alpinejs.in/retrieving-alpinejs-data-in-a-global-function</guid><category><![CDATA[alpinejs]]></category><category><![CDATA[data]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Tue, 04 Jul 2023 02:24:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/4ZPmkBGE3Fo/upload/2d224569f31c43b1510103df30e671b6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have a form coupled with AlpineJS.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>
<span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ first_name: '', last_name: '' }"</span>
<span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>
@<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"submitForm"</span>
&gt;</span>
</code></pre>
<p>I want the <code>x-data</code> details, <code>first_name</code> and <code>last_name</code> to be available in a global function.</p>
<p>One option is to retrieve the data via <code>this.$data</code> and other option is to pass the form data (which should be an array or an object) as an argument to the global function.</p>
<p>Passing the data as an object or as an array would reduce sending lots of arguments if there are, like, 30 or so variables.</p>
<p>Option 1: Get the data as <code>this.$data</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> submitForm = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)
</span>{        
    <span class="hljs-keyword">const</span> xData = <span class="hljs-built_in">this</span>.$data;

    <span class="hljs-keyword">const</span> first_name = xData.first_name;
    <span class="hljs-keyword">const</span> last_name = xData.last_name;

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"First Name:"</span>, first_name);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Last Name:"</span>, last_name);
};
</code></pre>
<p>Option2: Send the data as an argument to the function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> submitForm = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span>
{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data = "</span>, data);
};
</code></pre>
<p>But this is only if <code>x-data</code> is defined as <code>x-data="{ xData: { first_name: '', last_name: '' }}"</code> and the submit handler includes the argument - <code>@submit.prevent="submitForm2(xData)"</code>.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>
<span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ first_name: '', last_name: '' }"</span>
<span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>
@<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"submitForm1"</span>
&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
            First Name:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"first_name"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
            Last Name:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"last_name"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> submitForm1 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)
    </span>{        
        <span class="hljs-keyword">const</span> xData = <span class="hljs-built_in">this</span>.$data;

        <span class="hljs-keyword">const</span> first_name = xData.first_name;
        <span class="hljs-keyword">const</span> last_name = xData.last_name;

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"First Name:"</span>, first_name);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Last Name:"</span>, last_name);
    };
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">form</span>
    <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ xData: { first_name: '', last_name: '' }}"</span>
    <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>
    @<span class="hljs-attr">submit.prevent</span>=<span class="hljs-string">"submitForm2(xData)"</span>
    &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
            First Name:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"xData.first_name"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
            Last Name:
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"xData.last_name"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> submitForm2 = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span>
    {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"data = "</span>, data);
    };
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.12.3/dist/cdn.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Online Demo: <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/alpinejs-form-data.html">https://anjanesh.s3.amazonaws.com/demo/alpine/alpinejs-form-data.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Using Set instead of an Array]]></title><description><![CDATA[Let's say you had an object like this where you wanted to show the version numbers available for each type of application when the user checks an application. So if someone checks wordpress it should show the version numbers available, 6.2, 6.1, 5.9....]]></description><link>https://alpinejs.in/using-set-instead-of-an-array</link><guid isPermaLink="true">https://alpinejs.in/using-set-instead-of-an-array</guid><category><![CDATA[Sets]]></category><category><![CDATA[arrays]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[alpinejs]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Thu, 06 Apr 2023 02:02:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680746461459/a2e424ea-fe8e-4e23-8299-2d72c4b2bb2f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's say you had an object like this where you wanted to show the version numbers available for each type of application when the user checks an application. So if someone checks <strong>wordpress</strong> it should show the version numbers available, 6.2, 6.1, 5.9.</p>
<pre><code class="lang-javascript">{
    <span class="hljs-string">'php'</span>: [
        <span class="hljs-string">'8.2'</span>,
        <span class="hljs-string">'8.1'</span>,
        <span class="hljs-string">'8.0'</span>,
        <span class="hljs-string">'7.4'</span>,
        <span class="hljs-string">'7.2'</span>,
    ],
    <span class="hljs-string">'wordpress'</span>: [
            <span class="hljs-string">'6.2'</span>,
            <span class="hljs-string">'6.1'</span>,
            <span class="hljs-string">'5.9'</span>,
        ],
    <span class="hljs-string">'Apache'</span>: [
            <span class="hljs-string">'2.4'</span>,
            <span class="hljs-string">'2.2'</span>,
        ],
    <span class="hljs-string">'Python'</span>: [
            <span class="hljs-string">'3.11'</span>,
            <span class="hljs-string">'3.10'</span>,
            <span class="hljs-string">'3.9'</span>,
        ],
};
</code></pre>
<p>Using arrays we would do something like <code>show: []</code> and if the checkbox is checked we would push the key (<strong>wordpress</strong>) into the <code>show</code> array as a value. and if unchecked, we'll remove the key (value <strong>wordpress</strong> in <code>show</code>) from the <code>show</code> array.</p>
<p>So <code>show</code> would be <code>['wordpress']</code> when wordpress is checked and <code>['wordpress', 'apache']</code> when wordpress and apache are checked.</p>
<pre><code class="lang-javascript">
<span class="hljs-built_in">this</span>.event.target.checked ? show.push(key) : show.splice(show.indexOf(key))
</code></pre>
<p><code>show.push(key)</code> for pushing into the array and <code>show.splice(show.indexOf(key))</code> to remove from the array. They would be unique since we are adding and removing on-checked and unchecked. Otherwise, we would end up checking for the existence of a value in an array like this which would be unnecessary :</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">this</span>.event.target.checked ? (show.indexOf(key) === <span class="hljs-number">-1</span> ? show.push(key) : <span class="hljs-string">''</span>) : (show.indexOf(key) &gt;= <span class="hljs-number">0</span> ? show.splice(show.indexOf(key)) : <span class="hljs-string">''</span>)
</code></pre>
<p>So the AlpineJS code would be as follows :</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ applications: [], show: [] }"</span> <span class="hljs-attr">x-init</span>=<span class="hljs-string">"applications = await get_applications()"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"key in Object.keys(applications)"</span>&gt;</span>        
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex h-6 items-center"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">:id</span>=<span class="hljs-string">"key"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">:value</span>=<span class="hljs-string">"key"</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"this.event.target.checked ? show.push(key) : show.splice(show.indexOf(key))"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"key"</span> <span class="hljs-attr">:for</span>=<span class="hljs-string">"key"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">x-show</span>=<span class="hljs-string">"show.indexOf(key) &gt;= 0"</span> <span class="hljs-attr">:id</span>=<span class="hljs-string">"'select-' + key"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"app in applications[key]"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">:value</span>=<span class="hljs-string">"app"</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"app"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>If we were to use <code>Set</code> (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set</a>) instead then we could replace the array part like :</p>
<p><code>show: []</code> with <code>show: new Set()</code></p>
<pre><code class="lang-javascript"><span class="hljs-built_in">this</span>.event.target.checked ? show.push(key) : show.splice(show.indexOf(key))
</code></pre>
<p>with</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">this</span>.event.target.checked ? show.add(key) : show.delete(key)
</code></pre>
<p>and <code>show.indexOf(key) &gt;= 0</code> with <code>show.has(key)</code></p>
<p><strong>Demos :</strong></p>
<p>using Arrays - <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/arrays.html">https://anjanesh.s3.amazonaws.com/demo/alpine/arrays.html</a></p>
<p>Using Set - <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/set.html">https://anjanesh.s3.amazonaws.com/demo/alpine/set.html</a></p>
<p>Side Note: My <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/alpinejs-devtools/">AlpineJS dev tools</a> always show the Set Object to be empty even after selecting a check , though it isn't.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680745651703/d46f82eb-0cc1-4e37-8672-40985e08b4d1.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Using AlpineJS's $store magic]]></title><description><![CDATA[I was trying to explain reactiveness using AlpineJS to a colleague at work but failed to make a point which is the crux of how the DOM gets updated.
It's based on this blog post which has a demo.
I went on to explain that, by simply adding an entry (...]]></description><link>https://alpinejs.in/using-alpinejss-store-magic</link><guid isPermaLink="true">https://alpinejs.in/using-alpinejss-store-magic</guid><category><![CDATA[store]]></category><category><![CDATA[array]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Globals]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Tue, 28 Feb 2023 18:36:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677609326134/11974451-7877-4d3d-8c55-f66c256e4d03.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was trying to explain <em>react</em>iveness using AlpineJS to a colleague at work but failed to make a point which is the crux of how the DOM gets updated.</p>
<p>It's based on <a target="_blank" href="https://anjanesh.dev/displaying-data-an-array-of-objects-using-alpine-js-in-a-table">this blog post</a> which has a <a target="_blank" href="https://anjanesh.s3.amazonaws.com/div-form.html">demo</a>.</p>
<p>I went on to explain that, by simply adding an entry (entry being an object in this case) to the array will auto-magically update the DIV container by populating the new array's element into the HTML.</p>
<p>So I went ahead and did the obvious - (what I thought would / should work) - <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push"><code>push</code></a> an object into the array so that I can show him that the table gets a new row inserted without the need to write a single line of DOM manipulation code.</p>
<p>But there lay an issue where this didn't work! I tried to add an object to the array in the browser's console! Thing is, this will work only when pushed within the AlpineJS section - within where <code>x-data="{ data: content }"</code> is defined. Outside of this, there's no way to access AlpineJS's variables.</p>
<p>Here comes in the <a target="_blank" href="https://alpinejs.dev/magics/store">$store</a> magic.</p>
<p>It's like a global variable attached to AlpineJS's 'store' which has all the hooks to AlpineJS's functionality. It defeats the purpose of localized variables, but the only advantage of this is if you want to access variables from the outside or in the browser's console.</p>
<p>We basically add an event listener to when AlpineJS inititializes by <code>document.addEventListener("alpine:init")</code> and adding a data variable to it and a function to update the data.</p>
<pre><code class="lang-javascript">Alpine.store(<span class="hljs-string">'global_data'</span>,
{
    <span class="hljs-attr">data</span>: content,
    push(name, description)
    {
        <span class="hljs-built_in">this</span>.data.push({name, description});
    },
});
</code></pre>
<p>In the AlpineJS block we don't set the data in <code>x-data</code> - in this case we have it as <code>x-data="{}"</code></p>
<p>And in the button on-click, we call the <code>$store's</code> <strong>global_data</strong>'s <code>push</code> function</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">x-on:click</span>=<span class="hljs-string">"$store.global_data.push(document.getElementById('name').value, document.getElementById('description').value);"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;</span>Add<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>I've added a lone global <code>push</code> function just to call it from the outside for us to test :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> push = <span class="hljs-function">(<span class="hljs-params">name, description</span>) =&gt;</span>
{
    Alpine.store(<span class="hljs-string">'global_data'</span>).push(name, description);
}
</code></pre>
<p><img src="https://anjanesh.s3.amazonaws.com/demo/alpine/alpinejs-global-storage.gif" alt class="image--center mx-auto" /></p>
<p>Basically, this is direct access to the array in the browser console :</p>
<pre><code class="lang-javascript">Alpine.store(<span class="hljs-string">'global_data'</span>).data.push({<span class="hljs-attr">name</span>: <span class="hljs-string">'Test N'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Test DescriptionN'</span>});
</code></pre>
<p>I just demoed it using a function that just does this line above to make it shorter for typing.</p>
<p>Demo : <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/alpine/alpinejs-global-storage.html">https://anjanesh.s3.amazonaws.com/demo/alpine/alpinejs-global-storage.html</a></p>
<p>Gist: <a target="_blank" href="https://gist.github.com/anjanesh/86084b837bf6bc6acc43cbbbf923992f">https://gist.github.com/anjanesh/86084b837bf6bc6acc43cbbbf923992f</a></p>
]]></content:encoded></item><item><title><![CDATA[Using AlpineJS Template to load data from fetch]]></title><description><![CDATA[This is a follow-up to this post of mine where I show how to retrieve data from a public google spreadsheet via their JSON output and show it in the webpage by setting the HTML to a DOM element via innerHTML. I think doing something like document.get...]]></description><link>https://alpinejs.in/using-alpinejs-template-to-load-data-from-fetch</link><guid isPermaLink="true">https://alpinejs.in/using-alpinejs-template-to-load-data-from-fetch</guid><category><![CDATA[fetch]]></category><category><![CDATA[await]]></category><category><![CDATA[promises]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Mon, 23 Jan 2023 04:52:39 GMT</pubDate><content:encoded><![CDATA[<p>This is a follow-up to this <a target="_blank" href="https://anjane.sh/3CjKTeI">post of mine</a> where I show how to retrieve data from a public google spreadsheet via their JSON output and show it in the webpage by setting the HTML to a DOM element via <strong>innerHTML</strong>. I think doing something like <code>document.getElementById("razorui-faq").innerHTML = details;</code> is going to be considered bad practice shortly. Just like using <code>document.write()</code> is frowned upon.</p>
<p>With Reactive libraries and frameworks like React, Angular, Vue, Svelte etc being the standard for using <strong>templates</strong> in DOM replacement methodologies, it may not be suitable to use a whole <code>npm install</code> for smaller, micro-websites that are used for marketing purposes or using in an existing WordPress page.</p>
<p>There's a faster solution - <a target="_blank" href="https://alpinejs.dev/">AlpineJS</a> - it's <em>reactive</em> and has a smaller footprint and can be included in your webpage like you insert a jQuery CDN. Right now, all you got to do is to include <a target="_blank" href="https://unpkg.com/alpinejs@3.10.5/dist/cdn.min.js">https://unpkg.com/alpinejs@3.10.5/dist/cdn.min.js</a></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.10.5/dist/cdn.min.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>This - we use <a target="_blank" href="https://alpinejs.dev/directives/init">x-init</a> to fetch the data using await. Even the AlpineJS docs show it as <code>x-init="posts = await (await fetch('/posts')).json()"</code> as an example.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ faqs: [] }"</span> <span class="hljs-attr">x-init</span>=<span class="hljs-string">"faqs = await fetchFAQ().then((data) =&gt; data )"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">x-for</span>=<span class="hljs-string">"faq in faqs"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">details</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">summary</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"faq[0]"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">summary</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"faq[1]"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">details</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Get the content from the JSON as usual :</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getFAQ</span>(<span class="hljs-params">json</span>)
</span>{    
    <span class="hljs-keyword">let</span> faqList = [];
    <span class="hljs-keyword">let</span> detail, summary;

    json.table.rows.forEach(<span class="hljs-function">(<span class="hljs-params">row, i</span>) =&gt;</span>
    {
        <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// The first row is the header        </span>

        <span class="hljs-keyword">try</span> { detail = row.c[<span class="hljs-number">0</span>].f ? row.c[<span class="hljs-number">0</span>].f : row.c[<span class="hljs-number">0</span>].v }
        <span class="hljs-keyword">catch</span>(e){ detail = <span class="hljs-string">''</span> }

        <span class="hljs-keyword">try</span> { summary = row.c[<span class="hljs-number">1</span>].f ? row.c[<span class="hljs-number">1</span>].f : row.c[<span class="hljs-number">1</span>].v }
        <span class="hljs-keyword">catch</span>(e){ summary = <span class="hljs-string">''</span> }

        faqList.push([detail, summary]);
    });

    <span class="hljs-keyword">return</span> faqList;
}
</code></pre>
<p>The most <mark>important part</mark>: Using Promise by returning an <code>await new Promise</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> fetchFAQ = <span class="hljs-keyword">async</span> () =&gt;
{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span>
    {
        fetch(url)
        .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.text())
        .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span>
        {
            <span class="hljs-keyword">let</span> json_string = data.substring(<span class="hljs-number">47</span>).slice(<span class="hljs-number">0</span>, <span class="hljs-number">-2</span>);
            <span class="hljs-keyword">let</span> details = getFAQ(<span class="hljs-built_in">JSON</span>.parse(json_string));
            resolve(details);
        });
    });
}
</code></pre>
<p>Demo : <a target="_blank" href="https://anjanesh.s3.amazonaws.com/demo/fetch-alpine.html">https://anjanesh.s3.amazonaws.com/demo/fetch-alpine.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Replacing oninput with x-mask]]></title><description><![CDATA[<input type="text" pattern="[0-9,.]{0,10}"/>
Using the mask plugin we can achieve the comma separators inserted to the numbers in the text box instead of writing our own JavaScript.
Replace something like this we get from searching Google
oninput='th...]]></description><link>https://alpinejs.in/replacing-oninput-with-x-mask</link><guid isPermaLink="true">https://alpinejs.in/replacing-oninput-with-x-mask</guid><category><![CDATA[commas]]></category><category><![CDATA[numbers]]></category><category><![CDATA[HTML]]></category><category><![CDATA[plugin]]></category><category><![CDATA[alpinejs]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Wed, 30 Nov 2022 10:38:11 GMT</pubDate><content:encoded><![CDATA[<p><code>&lt;input type="text" pattern="[0-9,.]{0,10}"/&gt;</code></p>
<p>Using the <a target="_blank" href="https://alpinejs.dev/plugins/mask#x-mask">mask plugin</a> we can achieve the comma separators inserted to the numbers in the text box instead of writing our own JavaScript.</p>
<p>Replace something like this we get from searching Google</p>
<p><code>oninput='this.value = this.value.replace(/,/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",")'</code></p>
<p>with this :</p>
<p><code>x-mask:dynamic="$money($input)"</code></p>
<p>Finally :</p>
<pre><code class="lang-xml"><span class="hljs-comment">&lt;!-- Alpine Plugins --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/@alpinejs/mask@3.x.x/dist/cdn.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Alpine Core --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"bid"</span> 
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your bid amount"</span>
    <span class="hljs-attr">pattern</span>=<span class="hljs-string">"[0-9,.]{0,10}"</span>
    <span class="hljs-attr">x-mask:dynamic</span>=<span class="hljs-string">"$money($input)"</span>
/&gt;</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Show amount of money in Indian rupees as K / Lakhs / Crores]]></title><description><![CDATA[The method to convert a number to Indian currency as K / lakhs / crores is at :
https://anjanesh.dev/returning-amount-of-money-in-indian-ruppes-to-crores-lakhs-thousands
Here's the JavaScript equivalent using Intl.NumberFormat which is JavaScript's e...]]></description><link>https://alpinejs.in/show-amount-of-money-in-indian-rupees-as-k-lakhs-crores</link><guid isPermaLink="true">https://alpinejs.in/show-amount-of-money-in-indian-rupees-as-k-lakhs-crores</guid><category><![CDATA[alpinejs]]></category><category><![CDATA[currency]]></category><dc:creator><![CDATA[Anjanesh Lekshminarayanan]]></dc:creator><pubDate>Mon, 22 Aug 2022 03:58:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1661140797825/nG2v8WScJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The method to convert a number to Indian currency as K / lakhs / crores is at :
https://anjanesh.dev/returning-amount-of-money-in-indian-ruppes-to-crores-lakhs-thousands</p>
<p>Here's the JavaScript equivalent using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat">Intl.NumberFormat</a> which is JavaScript's equivalent to PHP's <code>number_format</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> INR_THOUSAND = <span class="hljs-number">1000</span>;
<span class="hljs-keyword">const</span> INR_LAKH = <span class="hljs-number">100</span> * INR_THOUSAND;
<span class="hljs-keyword">const</span> INR_CRORE = <span class="hljs-number">100</span> * INR_LAKH;

<span class="hljs-keyword">const</span> formatter = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.NumberFormat(<span class="hljs-string">'en'</span>, { <span class="hljs-attr">minimumFractionDigits</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">maximumFractionDigits</span>: <span class="hljs-number">2</span> });

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">amountInINR</span>(<span class="hljs-params">amount</span>)
</span>{
    INR = amount;
    ext = <span class="hljs-string">""</span>;

    <span class="hljs-keyword">if</span> (amount &gt; INR_CRORE)
    {
        INR = amount / INR_CRORE;
        ext = INR == <span class="hljs-number">1</span> ? <span class="hljs-string">"crore"</span> : <span class="hljs-string">"crores"</span>;
        INR = formatter.format(amount / INR_CRORE, <span class="hljs-number">2</span>) + <span class="hljs-string">' '</span> + ext;
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (amount &gt; INR_LAKH)
    {
        INR = amount / INR_LAKH;
        ext = INR == <span class="hljs-number">1</span> ? <span class="hljs-string">"lakh"</span> : <span class="hljs-string">"lakhs"</span>;
        INR = formatter.format(amount / INR_LAKH, <span class="hljs-number">2</span>) + <span class="hljs-string">' '</span> + ext;
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (amount &gt; INR_THOUSAND)
    {
        INR = amount / INR_THOUSAND;
        ext = INR == <span class="hljs-number">1</span> ? <span class="hljs-string">"lakh"</span> : <span class="hljs-string">"K"</span>;
        INR = formatter.format(amount / INR_THOUSAND, <span class="hljs-number">2</span>) + <span class="hljs-string">' '</span> + ext;
    }    
    <span class="hljs-keyword">else</span>
    {
        INR = formatter.format(amount, <span class="hljs-number">2</span>);
    }

    <span class="hljs-keyword">return</span> INR;
}
</code></pre>
<p>The AlpineJS's template :</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">x-data</span>=<span class="hljs-string">"{ indian_amount: '' }"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"amount"</span> <span class="hljs-attr">required</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"amount"</span> <span class="hljs-attr">x-model</span>=<span class="hljs-string">"indian_amount"</span> /&gt;</span>
  <span class="hljs-symbol">&amp;nbsp;</span>₹<span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">x-text</span>=<span class="hljs-string">"amountInINR(indian_amount)"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Full Demo - https://anjanesh.s3.amazonaws.com/demo/alpine/x-model-inr-currency.html</p>
<p>Update : <code>Intl.NumberFormat</code> has the option to get INR out of it but the notation display is a bit different - for example, thousands is represented as T and not K - and this does not work in Safari (version 14 is what I tested it on).</p>
<pre><code>let amountInINR <span class="hljs-operator">=</span> (amount) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Intl.NumberFormat(<span class="hljs-string">"en-IN"</span>, {
      style: <span class="hljs-string">"currency"</span>,
      currency: <span class="hljs-string">"INR"</span>,
      notation: <span class="hljs-string">"compact"</span>,
      compactDisplay: <span class="hljs-string">"long"</span>
    }).format(amount);
}
</code></pre><ul>
<li>36000 will return ₹36T</li>
<li>36000000 will return ₹3.6Cr</li>
<li>36000000000 will return  ₹3.6TCr </li>
</ul>
<p>Thanks to this <a target="_blank" href="https://stackoverflow.com/a/73441251/126833">StackOverflow answer</a>, <code>.replace()</code> is easiest to implement.</p>
<pre><code>let amountInINR <span class="hljs-operator">=</span> (amount) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span>
{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Intl.NumberFormat(<span class="hljs-string">"en-IN"</span>, {
      style: <span class="hljs-string">"currency"</span>,
      currency: <span class="hljs-string">"INR"</span>,
      notation: <span class="hljs-string">"compact"</span>,
      compactDisplay: <span class="hljs-string">"long"</span>,      
    }).format(amount).replace(<span class="hljs-string">'T'</span>, <span class="hljs-string">'K'</span>).replace(<span class="hljs-string">'L'</span>, <span class="hljs-string">' lakhs'</span>).replace(<span class="hljs-string">'Cr'</span>, <span class="hljs-string">' Crores'</span>);
}
</code></pre>]]></content:encoded></item></channel></rss>