<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JavaScript Archives - Michael Soriano</title>
	<atom:link href="https://michaelsoriano.com/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>https://michaelsoriano.com/category/javascript/</link>
	<description>I turn code into captivating user experiences for the web</description>
	<lastBuildDate>Wed, 14 Aug 2024 16:44:24 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.4</generator>
	<item>
		<title>Essential JavaScript Features You Probably Already Know &#8211; But Here It Is Anyway</title>
		<link>https://michaelsoriano.com/essential-javascript-features-you-probably-already-know/</link>
					<comments>https://michaelsoriano.com/essential-javascript-features-you-probably-already-know/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 12 Aug 2024 15:21:22 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=8154</guid>

					<description><![CDATA[<p>From time to time, I write real generic articles about JavaScript that may be common knowledge and/or that is featured in other websites and videos. These articles really serve myself a purpose. More like a &#8220;note to myself&#8221; &#8211; so instead of searching, I just go to my website and voila! Today it&#8217;s one of [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/essential-javascript-features-you-probably-already-know/">Essential JavaScript Features You Probably Already Know &#8211; But Here It Is Anyway</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>From time to time, I write real generic articles about JavaScript that may be common knowledge and/or that is featured in other websites and videos. These articles really serve myself a purpose. More like a &#8220;<em>note to myself</em>&#8221; &#8211; so instead of searching, I just go to my website and voila!</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="582" src="https://michaelsoriano.com/wp-content/uploads/2024/08/image-1-1024x582.jpg" alt="JavaScript code" class="wp-image-8158" srcset="https://michaelsoriano.com/wp-content/uploads/2024/08/image-1-1024x582.jpg 1024w, https://michaelsoriano.com/wp-content/uploads/2024/08/image-1-300x171.jpg 300w, https://michaelsoriano.com/wp-content/uploads/2024/08/image-1-768x437.jpg 768w, https://michaelsoriano.com/wp-content/uploads/2024/08/image-1.jpg 1036w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Today it&#8217;s one of those articles. We&#8217;re going to look at a few super useful JavaScript features that can make your coding life (<em>and mine</em>) a whole lot easier. Whether you&#8217;re just starting out or you&#8217;ve been coding for a while, these tools are worth adding to your toolkit.</p>



<p>Let&#8217;s dive in!</p>



<h2 class="wp-block-heading">1. Object.hasOwn(): A Safer Way to Check for Properties</h2>



<p>Have you ever needed to check if an object has a specific property? Maybe you&#8217;ve used the <code>in</code> operator or <code>Object.prototype.hasOwnProperty()</code> before. Well, <code>Object.hasOwn()</code> is here to make that task simpler and safer.</p>



<h3 class="wp-block-heading">How it works:</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">Object.hasOwn(object, propertyName)</code></pre>



<p>You pass in the object you want to check and the name of the property you&#8217;re looking for. It returns <code>true</code> if the object has that property as its own (not inherited), and <code>false</code> otherwise.</p>



<h3 class="wp-block-heading">Why it&#8217;s cool:</h3>



<p>Unlike <code>Object.prototype.hasOwnProperty()</code>, <code>Object.hasOwn()</code> works even if the object doesn&#8217;t inherit from <code>Object.prototype</code> or if it has its own <code>hasOwnProperty</code> method. It&#8217;s like a superhero version of <code>hasOwnProperty</code>!</p>



<h3 class="wp-block-heading">Before Object.hasOwn():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const person = { name: "Alice" };

// Old way (potentially unsafe)
if (person.hasOwnProperty("name")) {
  console.log("Person has a name");
}

// Safer old way
if (Object.prototype.hasOwnProperty.call(person, "name")) {
  console.log("Person has a name");
}</code></pre>



<h3 class="wp-block-heading">With Object.hasOwn():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const person = { name: "Alice" };

if (Object.hasOwn(person, "name")) {
  console.log("Person has a name");
}</code></pre>



<p>Much cleaner, right?</p>



<h2 class="wp-block-heading">2. String.replaceAll(): Find and Replace Made Easy</h2>



<p>This one is a game changer. I&#8217;m sure you&#8217;ve run into the old school replace &#8211; where it only does the first occurrence. I&#8217;m sure you&#8217;ll always almost need to replace ALL occurrences right? No more messing with regular expressions or some clever looping. Now, it&#8217;s as easy as pie!</p>



<h3 class="wp-block-heading">How it works:</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">string.replaceAll(searchValue, replaceValue)</code></pre>



<p>You provide the substring you want to replace and what you want to replace it with. It returns a new string with all matches replaced.</p>



<h3 class="wp-block-heading">Why it&#8217;s awesome:</h3>



<p>It&#8217;s straightforward and doesn&#8217;t require you to mess with regular expressions for simple replacements. Plus, it replaces ALL occurrences, not just the first one like <code>replace()</code> does.</p>



<h3 class="wp-block-heading">Before String.replaceAll():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const sentence = "The quick brown fox jumps over the lazy dog. The fox is quick!";

// Using regular expression
const newSentence = sentence.replace(/fox/g, "cat");

// Or using split and join
const newSentence2 = sentence.split("fox").join("cat");</code></pre>



<h3 class="wp-block-heading">With String.replaceAll():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const sentence = "The quick brown fox jumps over the lazy dog. The fox is quick!";
const newSentence = sentence.replaceAll("fox", "cat");</code></pre>



<p>So much easier to read and understand!</p>



<h2 class="wp-block-heading">3. structuredClone(): Deep Cloning Made Simple</h2>



<p>Another good one that will blow your mind. Let&#8217;s talk about <code>structuredClone()</code>. If you&#8217;ve ever tried to create a deep copy of an object in JavaScript, you know it can be tricky. This function makes it a breeze!</p>



<h3 class="wp-block-heading">How it works:</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const clone = structuredClone(original)</code></pre>



<p>You pass in the object you want to clone, and it returns a deep copy of that object.</p>



<h3 class="wp-block-heading">Why it&#8217;s fantastic:</h3>



<p>It can handle circular references, and it works with a wide variety of built-in types (like Date, Map, Set, and more). It&#8217;s also typically faster than other deep cloning methods.</p>



<h3 class="wp-block-heading">Before structuredClone():</h3>



<p>Can you say &#8220;yuck&#8221;?</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const original = { 
  name: "Alice", 
  pets: ["dog", "cat"],
  details: { age: 30 }
};

// Using JSON (loses some data types)
const jsonClone = JSON.parse(JSON.stringify(original));

// Or a custom recursive function (complex and error-prone)
function deepClone(obj) {
  if (typeof obj !== "object" || obj === null) return obj;
  const newObject = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    newObject[key] = deepClone(obj[key]);
  }
  return newObject;
}
const customClone = deepClone(original);</code></pre>



<h3 class="wp-block-heading">With structuredClone():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const original = { 
  name: "Alice", 
  pets: ["dog", "cat"],
  details: { age: 30 }
};

const clone = structuredClone(original);</code></pre>



<p>It&#8217;s like magic, isn&#8217;t it?</p>



<h2 class="wp-block-heading">4. Array.at(): Flexible Array Index Access</h2>



<p>Last one: ever wanted to access array elements from the end without knowing the array&#8217;s length? I&#8217;m sure you&#8217;ve done this hundreds of times. Well with <code>Array.at()</code> &#8211; your development life is going to be a tad better. </p>



<h3 class="wp-block-heading">How it works:</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">array.at(index)</code></pre>



<p>You provide an index, which can be positive or negative. Positive indices work like normal array access, while negative indices count from the end of the array.</p>



<h3 class="wp-block-heading">Why it&#8217;s great:</h3>



<p>It provides a clean way to access elements relative to the end of an array without needing to know its length. It&#8217;s especially useful for accessing the last few elements of an array.</p>



<h3 class="wp-block-heading">Before Array.at():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const fruits = ['apple', 'banana', 'cherry', 'date'];

// Getting the last element
const lastFruit = fruits[fruits.length - 1];

// Getting the second to last element
const secondToLastFruit = fruits[fruits.length - 2];</code></pre>



<h3 class="wp-block-heading">With Array.at():</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const fruits = ['apple', 'banana', 'cherry', 'date'];

// Getting the last element
const lastFruit = fruits.at(-1);

// Getting the second to last element
const secondToLastFruit = fruits.at(-2);</code></pre>



<p>It&#8217;s more readable and less error-prone, especially when dealing with array lengths!</p>



<p>And there you have it!   Super handy JavaScript features that can make your code cleaner, safer, and more efficient. Give them a try in your next project and see how they can level up your coding game.</p>



<p>Before you go, you might also find this one useful:  <a href="https://michaelsoriano.com/common-javascript-snippets-for-data-manipulation/">Common JavaScript snippets for data manipulation</a></p>



<p>Happy coding!</p>
<p>The post <a href="https://michaelsoriano.com/essential-javascript-features-you-probably-already-know/">Essential JavaScript Features You Probably Already Know &#8211; But Here It Is Anyway</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/essential-javascript-features-you-probably-already-know/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to create an Accordion Block using React and WordPress&#8217; Block API</title>
		<link>https://michaelsoriano.com/how-to-create-an-accordion-block-using-react-and-wordpress-block-api/</link>
					<comments>https://michaelsoriano.com/how-to-create-an-accordion-block-using-react-and-wordpress-block-api/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 06 Nov 2023 23:03:50 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7969</guid>

					<description><![CDATA[<p>I was tasked with creating a custom component for our public website which runs on WordPress. Most commonly known as an &#8220;Accordion&#8220;, it is a section of a page where you can have a title and an expandable and collapsible directly underneath it. Usually a list of these items are blocked together &#8211; forming an [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/how-to-create-an-accordion-block-using-react-and-wordpress-block-api/">How to create an Accordion Block using React and WordPress&#8217; Block API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I was tasked with creating a custom component for our public website which runs on WordPress. Most commonly known as an &#8220;<em>Accordion</em>&#8220;, it is a section of a page where you can have a title and an expandable and collapsible directly underneath it. Usually a list of these items are blocked together &#8211; forming an &#8220;accordion&#8221; like pattern. </p>



<p>In HTML, this is easily achieved by the &#8220;<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details"><strong>Details</strong></a>&#8221; element. But of course, our users cannot write HTML. Similarly, a default block already exists in WordPress called &#8220;<em>details</em>&#8220;. The problem with this one is that our users do not find it intuitive. Also, they want to limit the formatting of the contents for each item. </p>



<figure class="wp-block-image size-large border"><img decoding="async" width="1024" height="510" src="https://michaelsoriano.com/wp-content/uploads/2023/11/image-1024x510.png" alt="" class="wp-image-7973" srcset="https://michaelsoriano.com/wp-content/uploads/2023/11/image-1024x510.png 1024w, https://michaelsoriano.com/wp-content/uploads/2023/11/image-300x149.png 300w, https://michaelsoriano.com/wp-content/uploads/2023/11/image-768x383.png 768w, https://michaelsoriano.com/wp-content/uploads/2023/11/image-1536x765.png 1536w, https://michaelsoriano.com/wp-content/uploads/2023/11/image.png 1662w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>You see how each item is contained within a big block. A button will add a title/content pair to the list &#8211; along with a checkbox that allows for the section to be expanded or collapsed by default. </p>



<h3 class="wp-block-heading">Register the Block </h3>



<p>This is the &#8220;housekeeping&#8221; part of the codebase. There is a PHP part of this process &#8211; and it really depends if you&#8217;re putting this in a plugin or a theme. But main function is below:</p>



<pre class="wp-block-code"><code lang="php" class="language-php">register_block_type(
    'namepsace/my-blocks-accordion',  // Block name with namespace
    [
        'style' => 'accordion-style',  
        'editor_style' => 'accordion-edit-style', 
        'editor_script' => 'accordion-js'  
    ]
);
...</code></pre>



<p>Also, there are other parts of this such as enqueuing the styles and scripts for your blocks &#8211; which I&#8217;m not going to cover here. We&#8217;re mostly focusing on the &#8220;client&#8221; or JS side of things. </p>



<p>To read more about registering blocks in WordPress &#8211; see the <a href="https://developer.wordpress.org/reference/functions/register_block_type/">codex</a>.  </p>



<p>For the JavaScript, create a file called <em>index.js</em> and start with the <strong>registerBlockType</strong>() function. If you&#8217;re not familiar with how to build blocks for WP &#8211; this is a good start <a href="https://developer.wordpress.org/block-editor/getting-started/create-block/block-anatomy/">Anatomy of a Block | Block Editor Handbook | WordPress Developer Resources</a>.</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">registerBlockType(
    'namespace/accordion', {
      title: __('Accordion'),  
      icon: 'list-view',
      category: 'my-blocks', 
      attributes : {
        items : { 
         type: 'array',
         default : []
     }
    ...
}</code></pre>



<p>Pay extra attention to the &#8220;<em>attributes</em>&#8221; object. This is the main &#8220;context&#8221; of our application. Notice that we want an array called &#8220;items&#8221; inside attributes &#8211; this is where we&#8217;ll manage our data.  </p>



<h3 class="wp-block-heading">The &#8220;Edit&#8221; Component</h3>



<p>So in Gutenberg Blocks, the two major components that we have to worry about is the &#8220;Edit&#8221; and &#8220;Save&#8221;. Edit is what you see during the editing of Posts or Pages. Let&#8217;s look at how to build this first &#8211; particularly the JSX section:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">const { RichText } = wp.editor;  
const { __ } = wp.i18n;

...

title: __('Accordion'),  
icon: 'list-view',
category: 'my-blocks', 
attributes : {
   items : { 
     type: 'array',
     default : []
   }
},
edit ( {className, attributes, setAttributes} ) {

... 

return (
&lt;div>
{attributes.items &amp;&amp; attributes.items.length > 0 ? attributes.items.map((item,i) => {
return (
&lt;div>
    &lt;div className={`${className}-item-title-wrap`}>
    &lt;RichText   
        allowedFormats={[]}   
        tagName="div"     
        placeholder="Enter Title"               
        className={ `${className}-item-title` }
        value={ item.title }
        disableLineBreaks={ true }
        onChange={ val => updateItemTitle(val,i)}
    />
    &lt;label>
    &lt;input type="checkbox" data-index={i}
        checked={item.expand} 
        onChange={e=>updateItemExpand(e)} />
        Expanded
    &lt;/label>
    &lt;/div>
    &lt;RichText  
        placeholder="Enter Content"  
        allowedFormats={ ['core/bold','core/italic','core/link'] }    
        multiline="p"
        tagName="div"                    
        className={ `${className}-item-content` }
        value={item.content}
        onChange={ val => updateItemContent(val,i)}
    />
&lt;/div>
)
}) : null}
&lt;button 
    className={ `${className}-add-btn` } 
    onClick={addEmptyItem}>Add Accordion Item&lt;/button>
&lt;/div>
);

} //END EDIT</code></pre>



<p>The HTML above is the UI for our editors. Notice that we&#8217;re going through out &#8220;<em>items</em>&#8221; and outputting it for action. We&#8217;re using the built-in <strong>RichText</strong> component for our editable sections (title and content). RichText is awesome &#8211; <a href="https://developer.wordpress.org/block-editor/reference-guides/richtext/">find out</a> more about it. We&#8217;re also including a checkbox called <em>expanded</em> &#8211; that will allow our users to show the item expanded or collapsed. </p>



<h3 class="wp-block-heading">Adding Items</h3>



<p>When first using the block &#8211; all you see is a button that says &#8220;<em>Add Accordion Item</em>&#8220;. Clicking this button will execute below:</p>



<pre class="wp-block-code"><code lang="JavaScript" class="language-JavaScript">const addEmptyItem = () =&gt; {
    const items = [...attributes.items, {
      title : '', 
      content : '', 
      expand : true
    }];
   setAttributes({items})
}</code></pre>



<p>This will add an empty object to our Attributes Items array, allowing our users to be able to edit our RichText components. </p>



<h3 class="wp-block-heading">Click and Change Handlers</h3>



<p>If you look in our JSX, we&#8217;ve mapped our inputs to event handlers. Add the code below&#8221;</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">const updateItemExpand= (e) => {
    const items = attributes.items.slice();
    const index = e.target.attributes.getNamedItem('data-index').value;
    items[index].expand = e.target.checked;
    setAttributes({items})
}
const updateItemTitle = (title,i) => {
    const items = attributes.items.slice();
    items[i].title = title;
    setAttributes({items})
}
const updateItemContent = (content,i) => {
    const items = attributes.items.slice();
    items[i].content = content;
    setAttributes({items})
}</code></pre>



<p>The function names are pretty self explanatory. All we&#8217;re doing is manipulating the data in our Attributes. Also notice the <strong>setAttributes</strong>() function we&#8217;re using in each function. This is a &#8220;setter&#8221; that is very similar to React&#8217;s <em>useState</em> setters.  </p>



<p>With all that in place, our Accordion block is ready for editing:</p>



<figure class="wp-block-image size-full border wp-duotone-unset-1"><img decoding="async" width="923" height="520" src="https://michaelsoriano.com/wp-content/uploads/2023/11/accordion-block-edit.gif" alt="" class="wp-image-7971"/></figure>



<p>Typing &#8220;<em>/accordion</em>&#8221; will insert our block &#8211; ready for editing. </p>



<h3 class="wp-block-heading">The &#8220;Save&#8221; Component</h3>



<p>This is simply JSX that outputs our HTML for the public users. The code for this is quite simple &#8211; we&#8217;re simply using &#8220;<strong>details</strong>&#8221; and &#8220;<strong>summary</strong>&#8220;. This automatically has the expand and collapse functionality out of the box.</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">save( { attributes } ) {
    return (
        &lt;div>
        {attributes.items &amp;&amp; attributes.items.length > 0 ? (
            attributes.items.map(item => {
                return (
                    &lt;details open={item.expand}>
                    &lt;summary>{item.title}&lt;/summary>
                    &lt;div dangerouslySetInnerHTML={
                       {__html: item.content}
                    } /> 
                    &lt;/details>
                )
            })
        ) : null}
        &lt;/div>
        )
    } 
}</code></pre>



<p>Notice the use of <em>dangerouslySetInnerHTML</em> &#8211; because we&#8217;re outputting HTML content from WordPress. If this can be done in other ways leave a comment below. </p>



<p>Styling the output with some CSS:</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.wp-block-my-blocks-accordion {
    margin-bottom: 25px;
}

.wp-block-my-blocks-accordion details > summary {
    background:url('/images/arrow-down.png') no-repeat;
    background-size: 13px;
    background-position-x: right;
    background-position-y: 10px;
    font-weight: 500;
    border-bottom:1px solid #ebebeb;
    margin-bottom: 10px;
    padding-bottom: 6px;
    cursor:pointer;
}
.wp-block-my-blocks-accordion details[open] > summary {
    background:url('images/arrow-up.png') no-repeat;
    background-size: 13px;
    background-position-x: right;
    background-position-y: 10px;
} 
.wp-block-my-blocks-accordion details > summary:hover {
    opacity: 0.6;
}  
.wp-block-my-blocks-accordion details > summary > * {
    display: inline;
}</code></pre>



<p>We&#8217;re simply overriding the default look of the details component &#8211; specifically the arrows. I prefer to see them in the right instead of left. Also, adding a subtle border to make it look better. </p>



<p>And with that in place &#8211; it should look like below when the post is saved:</p>



<figure class="wp-block-image size-full border"><img decoding="async" width="788" height="494" src="https://michaelsoriano.com/wp-content/uploads/2023/11/accordion-block-view.gif" alt="" class="wp-image-7972"/></figure>



<p>There you have it. We&#8217;ve just made our own custom Gutenberg block. This was pretty fun to build &#8211; and learning about the Block API is quite straightforward. It&#8217;s very much like classic React &#8211; but simpler.</p>



<p>Be sure to leave your thoughts below.</p>
<p>The post <a href="https://michaelsoriano.com/how-to-create-an-accordion-block-using-react-and-wordpress-block-api/">How to create an Accordion Block using React and WordPress&#8217; Block API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/how-to-create-an-accordion-block-using-react-and-wordpress-block-api/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Let&#8217;s write a simple search component using React and FluentUI</title>
		<link>https://michaelsoriano.com/lets-write-a-simple-search-component-using-react-and-fluentui/</link>
					<comments>https://michaelsoriano.com/lets-write-a-simple-search-component-using-react-and-fluentui/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Tue, 26 Sep 2023 00:17:54 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7949</guid>

					<description><![CDATA[<p>I&#8217;ve been using a lot of FluentUI lately. This is mainly because my work has chosen the Microsoft stack for our intranet portal. FluentUI keeps the look of our apps consistent across the board &#8211; so users won&#8217;t be able to tell custom code and off the shelf. FluentUI uses React under the hood, so [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/lets-write-a-simple-search-component-using-react-and-fluentui/">Let&#8217;s write a simple search component using React and FluentUI</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve been using a lot of FluentUI lately. This is mainly because my work has chosen the Microsoft stack for our intranet portal. FluentUI keeps the look of our apps consistent across the board &#8211; so users won&#8217;t be able to tell custom code and off the shelf. </p>



<p>FluentUI uses React under the hood, so the tutorial below is meant for React developers. A preview of how the search works is shown below.   </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="636" height="594" src="https://michaelsoriano.com/wp-content/uploads/2023/09/fluentui-search.gif" alt="" class="wp-image-7954"/></figure>



<p>Ready to code? Let&#8217;s begin. </p>



<h3 class="wp-block-heading">Getting the items</h3>



<p>So assuming you&#8217;re getting you list of items via fetch, you&#8217;re most likely going to have an &#8220;init&#8221;. In React, this is done using the <strong>useEffect</strong> hook &#8211; with an empty dependency array. We&#8217;re also setting a couple of getters and setters using state:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">const [ links, setLinks ] = React.useState&lt;LinkType[]&gt;([]);
const [ allLinks, setAllLinks ]= React.useState&lt;LinkType[]&gt;([]);

useEffect(()=&gt;{
   (async()=&gt;{
       const items  = await fetch(...);            
       setLinks(items);
       setAllLinks(items);
     })()
 },[])</code></pre>



<p>You&#8217;re probably wondering why we have two states &#8220;links&#8221; and &#8220;allLinks&#8221;. This is to store the &#8220;unfiltered&#8221; set of items (allLinks) on which we do a search on &#8211; while the results will be in &#8220;links&#8221;.</p>



<p>So this will load our items in our display when we first load our UI. </p>



<h3 class="wp-block-heading">The Text input</h3>



<p>Now let&#8217;s add a text input. You will realize that the HTML are all different &#8211; because they&#8217;re not regular  HTML at all. Instead, they&#8217;re a bunch of wrappers designed by <a href="https://developer.microsoft.com/en-us/fluentui#/controls/web">FluentUI</a> in which we simply just have to learn what we can pass into it.  </p>



<p>In our case, we&#8217;re passing an icon (a magnifying glass), a placeholder, some styles and an onChange event to the &#8220;<strong>TextField</strong>&#8221; component:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">&lt;TextField 
   iconProps={{ iconName: 'Search' }} 
   placeholder="Search for a link..." 
   onChange={doSearch} styles={getStyles}  /&gt;</code></pre>



<p>I want to first focus on the <strong>getStyles</strong> function below. Notice that it just returns an object that contains CSS props as an array &#8211; for the nodes you want to target. Think of it as in regular HTML, when you design an input &#8211; you&#8217;d have to add a &#8220;label&#8221;, &#8220;fieldGroup&#8221;, &#8220;input&#8221; etc.  </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">function getStyles(props: ITextFieldStyleProps): Partial&lt;ITextFieldStyles&gt; {
         return {
          fieldGroup: [
            { 
                marginTop : '15px',
                marginLeft : '8px',
                borderColor : '#c0c0c0',
                maxWidth: '224px',
            }
          ],
          subComponentStyles: {
             label: { ...labelstyles },
           },
        };
      }</code></pre>



<p>You&#8217;ll be seeing a lot of this type of API throughout. </p>



<p>Let&#8217;s also add another state for the searchTerm: </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">const [ searchTerm, setSearchTerm ] = React.useState&lt;string&gt;('');</code></pre>



<p>Add a function &#8220;doSearch&#8221; so we can tie it with our TextField&#8217;s onChange event. Every time we change it, it should update our state:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">const doSearch = (e, val) : void =&gt; {
   setSearchTerm(val);   
}</code></pre>



<p>Now let&#8217;s create another effect, that will filter our items:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">useEffect(()=&gt;{    
        if(searchTerm === ''){
            setItems(allLinks);
        }else{
            const filtered = allLinks.filter(link =&gt; {
                const title = link.Title.toLowerCase();
                return title.indexOf(searchTerm) !== -1;
              }).map(link =&gt; {
                return {
                  ...link, 
                  Highlighted : highlightTerm(searchTerm, link.Title)
              }})
            setItems(filtered); 
        }
 },[searchTerm])</code></pre>



<p>One quick note is the dependency array &#8211; we have &#8220;<strong>searchTerm</strong>&#8220;. So this triggers every time our state changes. So if there is no term &#8211; we reset the items to &#8220;alltems&#8221;, otherwise &#8211; we do a &#8220;<em>filter</em>&#8221; on our items array.  </p>



<p>The search algorithm is just a basic string match &#8211; which can be greatly improved. But that&#8217;s not the focus of this tutorial. </p>



<p>You&#8217;ll also notice a .map &#8211; where we add a &#8220;<em>Highlighted</em>&#8221; property. That comes next.</p>



<h3 class="wp-block-heading">Highlighting the term</h3>



<p>It&#8217;s always a nice touch to highlight the search term in the results. This is a little helper that is called to wrap the term in a &#8220;mark&#8221; tag &#8211; so we can style it. </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">export function highlightTerm(term : string, src : string) : string {               
    if(term &amp;&amp; src){
      term = term.replace(/(\s+)/,"(&lt;[^&gt;]+&gt;)*$1(&lt;[^&gt;]+&gt;)*");
      const pattern = new RegExp(`(${term})`, "gi");
      src = src.replace(pattern, "&lt;mark&gt;$1&lt;/mark&gt;");
      src = src.replace(/(&lt;mark&gt;[^&lt;&gt;]*)((&lt;[^&gt;]+&gt;)+)([^&lt;&gt;]*&lt;\/mark&gt;)/,"$1&lt;/mark&gt;$2&lt;mark&gt;$4");
      return src;
    } 
    return src;
}</code></pre>



<p>Now that all our elements are in place, its time for the display. </p>



<h3 class="wp-block-heading">Displaying the results</h3>



<p>This section should be really familiar &#8211; its just a map that returns some JSX:</p>



<pre class="wp-block-code"><code lang="JavaScript" class="language-JavaScript">{links.map(link =&gt; {
      return (
         &lt;div dangerouslySetInnerHTML={{__html:item.Highlighted}}/&gt;
      )
 })}       </code></pre>



<p>Notice the use of <em>dangerouslySetInnerHTML</em> &#8211; that&#8217;s because we want our &#8220;mark&#8221; which is HTML to show. </p>



<figure class="wp-block-image size-large is-resized border"><img decoding="async" width="1024" height="787" src="https://michaelsoriano.com/wp-content/uploads/2023/09/image-1024x787.png" alt="" class="wp-image-7964" style="width:531px;height:408px" srcset="https://michaelsoriano.com/wp-content/uploads/2023/09/image-1024x787.png 1024w, https://michaelsoriano.com/wp-content/uploads/2023/09/image-300x231.png 300w, https://michaelsoriano.com/wp-content/uploads/2023/09/image-768x590.png 768w, https://michaelsoriano.com/wp-content/uploads/2023/09/image.png 1246w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>This is as simple as it gets. As mentioned before &#8211; the actual search mechanism can be better. I also would like to see some &#8220;loading&#8221; mechanism &#8211; for instances that the data takes long to fetch. And of course &#8211; some error handling would be good. </p>



<p>Leave your thoughts below. </p>
<p>The post <a href="https://michaelsoriano.com/lets-write-a-simple-search-component-using-react-and-fluentui/">Let&#8217;s write a simple search component using React and FluentUI</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/lets-write-a-simple-search-component-using-react-and-fluentui/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Use sessionStorage for caching data from your  backend API</title>
		<link>https://michaelsoriano.com/use-sessionstorage-for-caching-data-from-your-backend-api/</link>
					<comments>https://michaelsoriano.com/use-sessionstorage-for-caching-data-from-your-backend-api/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Fri, 28 Apr 2023 00:06:29 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7913</guid>

					<description><![CDATA[<p>Full stack applications that are decoupled (when the front end is totally detached from the backend) can have a lot of drawbacks. One of those is when communication between the two takes too long. Laggy response times from your backend greatly depreciates the user experience. Nobody likes waiting for stuff to load. And no &#8211; [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/use-sessionstorage-for-caching-data-from-your-backend-api/">Use sessionStorage for caching data from your  backend API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Full stack applications that are decoupled (when the front end is totally detached from the backend) can have a lot of drawbacks. One of those is when communication between the two takes too long. Laggy response times from your backend greatly depreciates the user experience. </p>



<p>Nobody likes waiting for stuff to load. And no &#8211; <em>loading spinners</em> is not a solution.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="576" src="https://michaelsoriano.com/wp-content/uploads/2023/04/photo-1477466535227-9f581b3eec21-1024x576.webp" alt="" class="wp-image-7922" srcset="https://michaelsoriano.com/wp-content/uploads/2023/04/photo-1477466535227-9f581b3eec21-1024x576.webp 1024w, https://michaelsoriano.com/wp-content/uploads/2023/04/photo-1477466535227-9f581b3eec21-300x169.webp 300w, https://michaelsoriano.com/wp-content/uploads/2023/04/photo-1477466535227-9f581b3eec21-768x432.webp 768w, https://michaelsoriano.com/wp-content/uploads/2023/04/photo-1477466535227-9f581b3eec21-1536x864.webp 1536w, https://michaelsoriano.com/wp-content/uploads/2023/04/photo-1477466535227-9f581b3eec21.webp 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Of course, you can cache the responses in the backend. But that means either you have to use some kind of storage in the server &#8211; such as a database This solution caches the responses in the client&#8217;s browser &#8211; using <strong>sessionStorage</strong>.  </p>



<p>It is not unusual to see code like this:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx line-numbers">useEffect(()=&gt;{
    (async()=&gt;{
       let data : FeedType = {}
       const resp = await fetch(`/get-feed/${id}`)
       data = await resp.json(); 
       setData(data)
    })();
},[])</code></pre>



<p>Wouldn&#8217;t it be great if it doesn&#8217;t do the fetch to the backend at all? </p>



<p>Remember, this is only recommended if your application doesn&#8217;t require real time data. If you can afford to serve cached data (say 15 mins) &#8211; then this solution is for you. </p>



<p>First, let&#8217;s write the cache to sessionStorage. </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx line-numbers">useEffect(()=>{
    (async()=>{
       let data : FeedType = {};
       const resp = await fetch(`/get-feed/${id}`);
       data = await resp.json(); 
       
       const currentTimeStamp = Math.floor(Date.now() / 1000);
       data.cacheSet = currentTimeStamp;
       sessionStorage.setItem(`id-${id}`, JSON.stringify(data));


       setData(data)
    })();
},[])</code></pre>



<p>Right after we get the data from the backend we write to sessionStorage with a unique key. This key is necessary for later retrieval. We&#8217;re also adding a timestamp on when we created the cache &#8211; this will come in handy for later.</p>



<p>Let&#8217;s create a function that gets the cache:</p>



<pre class="wp-block-code"><code lang="typescript" class="language-typescript line-numbers">const getCache = (id : number) : {isCacheGood : boolean, data : FeedType} => {
    let isCacheGood = false;
    let data : { cacheSet ?: number}= {};
    const currentTimeStamp = Math.floor(Date.now() / 1000); 
    const threshold = 900; //15 minutes   
    const cacheStr = sessionStorage.getItem(`id-${id}`); 
  
    if(cacheStr){ 
        data = JSON.parse(cacheStr);
        if(data.cacheSet){
            const numSeconds = Math.abs(currentTimeStamp - data.cacheSet);
            if(numSeconds &lt; threshold){
                isCacheGood = true;
            } 
        }
    }
    return {
        isCacheGood : isCacheGood,
        data : data
    }
}</code></pre>



<p>As you can see, just a simple function that gets the sessionStorage with our unique key.  It also converts the JSON string back to an object for consumption later. Also, the logic for checking if the cache is good is in here. It return true if its less than the threshold we set (in our case 15 minutes). </p>



<p>Now, let&#8217;s modify our code to not fetch when cache is found and good:</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx line-numbers">useEffect(()=>{
    (async()=>{
       let data : FeedType = {};

       const dataFromCache = getCache(id);
  
       if(dataFromCache.isCacheGood){
          data = dataFromCache.data
       }else{
          const resp = await fetch(`/get-feed/${id}`);
          data = await resp.json(); 
          const currentTimeStamp = Math.floor(Date.now() / 1000);
          data.cacheSet = currentTimeStamp;
          sessionStorage.setItem(`id-${id}`, JSON.stringify(data));
       }

       setData(data)
    })();
},[])</code></pre>



<p>So now, we first check if cache is good and use it for our data. Otherwise, we do a fetch &#8211; and write to cache. </p>



<h3 class="wp-block-heading">What about invalidation?</h3>



<p>Good question. We don&#8217;t want to keep writing to cache and not clean up right? The good thing is, sessionStorage automatically gets cleared once the user closes the browser session. Also, remember the unique key that we set &#8211; well, that keeps getting overwritten &#8211; if its the same response. </p>



<p>Let me know your thoughts below. </p>
<p>The post <a href="https://michaelsoriano.com/use-sessionstorage-for-caching-data-from-your-backend-api/">Use sessionStorage for caching data from your  backend API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/use-sessionstorage-for-caching-data-from-your-backend-api/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Code a multi-select input with Mantine, Prisma and NextJS</title>
		<link>https://michaelsoriano.com/multi-select-input-mantine-prisma-nextjs/</link>
					<comments>https://michaelsoriano.com/multi-select-input-mantine-prisma-nextjs/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Tue, 15 Nov 2022 23:05:55 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7847</guid>

					<description><![CDATA[<p>We&#8217;ve all seen this input before. A seemingly innocent input box and as soon as you focus and/or start typing &#8211; a list of suggestions appear. Not only that, you&#8217;re able to select multiple values, remove items from your selection &#8211; and even add a new one. This is typically used for fields such as [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/multi-select-input-mantine-prisma-nextjs/">Code a multi-select input with Mantine, Prisma and NextJS</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>We&#8217;ve all seen this input before. A seemingly innocent input box and as soon as you focus and/or start typing &#8211; a list of suggestions appear. Not only that, you&#8217;re able to select multiple values, remove items from your selection &#8211; and even add a new one. This is typically used for fields such as &#8220;<em>categories</em>&#8221; or &#8220;<em>tags</em>&#8221; &#8211; where you can enter multiple values to a single record. </p>



<p>Disclaimer: This tutorial will not show how to make this component, instead we&#8217;ll go through how to hook it up to the backend. I&#8217;m also going to assume you know <strong>React</strong> and <strong>databases</strong>. </p>



<p>Ready to get started? Let&#8217;s go: </p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1024x655.png" alt="" class="wp-image-7854" width="691" height="441" srcset="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1024x655.png 1024w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-300x192.png 300w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-768x491.png 768w, https://michaelsoriano.com/wp-content/uploads/2022/11/image.png 1522w" sizes="(max-width: 691px) 100vw, 691px" /></figure>



<p>We&#8217;re using Mantine&#8217;s <a href="https://mantine.dev/core/multi-select/">MultiSelect</a> &#8211; which has a pretty consistent api &#8211; with other mutli selects out there. I also like Mantine&#8217;s accessibility, and its simplicity. We&#8217;re also using <a href="https://www.prisma.io/">Prisma for our ORM</a> &#8211; which makes it super easy to interact with our tables in the backend. </p>



<h3 class="wp-block-heading">The Data / Tables</h3>



<p>For this application, I have a main table called &#8220;Dish&#8221;. This is where we will connect our &#8220;Categories&#8221;. But for this work, we will need a &#8220;many to many&#8221; relation &#8211; so we will need a 3rd table &#8211; we&#8217;ll call it <em>CategoriesOnDishes</em>. </p>



<p>Below is the schema for tables. </p>



<pre class="wp-block-code"><code lang="typescript" class="language-typescript">model Dish {
  id          Int                   @id @default(autoincrement())
  title       String
  ...
  categories  CategoriesOnDishes[]
}

model Category {
  id          Int                  @id @default(autoincrement())
  name        String
  default     Boolean?
  dishes      CategoriesOnDishes[]
}

//THIS IS THE LOOKUP TABLE
model CategoriesOnDishes { 
  dish       Dish     @relation(fields: [dishId], references: [id], onDelete: Cascade)
  dishId     Int
  category   Category @relation(fields: [categoryId], references: [id])
  categoryId Int
  @@id([dishId, categoryId])
}</code></pre>



<p>Notice our &#8220;lookup table&#8221; is simply the <em>connecting</em> table for both main tables. This way we can assign multiple ids to each other. </p>



<h3 class="wp-block-heading">The MultiSelect Component</h3>



<p>Looking at <a href="https://mantine.dev/">Mantine&#8217;s documentation,</a> our component simply takes in an array of objects, with 2 properties: value and label:</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-1-1024x785.jpg" alt="" class="wp-image-7857" width="671" height="513" srcset="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-1-1024x785.jpg 1024w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-1-300x230.jpg 300w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-1.jpg 1422w" sizes="(max-width: 671px) 100vw, 671px" /></figure>



<p>We also have access which values the user selected &#8211; which is simply an array of strings. With this in mind, we can go ahead and build our app.</p>



<h3 class="wp-block-heading">Get the categories</h3>



<p>We&#8217;re using NextJS &#8211; so we can create API endpoints and interact with our database. We wouldn&#8217;t be able to achieve this with only client side code. With NextJS &#8211; we have the luxury of both, in one codebase &#8211; how nice is that.</p>



<p>In our endpoint, we simply check the method for &#8220;GET&#8221; and bring back the categories for selection in our component:</p>



<pre class="wp-block-code"><code lang="typescript" class="language-typescript">if(req.method === 'GET'){ //THIS IS FOR GETTING THE VALUES FOR THE SELECT
    
        let data  : Categories[] = [];
        data  = await prisma?.category.findMany() as Categories[];

            const uniqueValuesSet = new Set();
            
            //REMOVE DUPLICATE NAMES... 
            data = data.filter((item)=&gt;{ 
                const isPresentInSet = uniqueValuesSet.has(item.name);  
                uniqueValuesSet.add(item.name);         
                return !isPresentInSet;
            })
        }
        return res.status(200).json({ categories : data  })
    }</code></pre>



<p>Notice that we have a remove duplicates section &#8211; this is optional. In my application, there could be duplicates due to the categories are based on each user / dish. </p>



<h3 class="wp-block-heading">The Component</h3>



<p>Now in the front end, we add the component to our form. You will notice a lot of this code doesn&#8217;t show the entire thing. I have greatly trimmed it down &#8211; only to highlight the important parts. </p>



<pre class="wp-block-code"><code lang="typescript" class="language-typescript">function CategorySelect( props:any) {
    const [ catOptions, setCatOptions ] = useState&lt;any&gt;();

    useEffect(()=&gt;{
        (async()=&gt;{
            const resp = await fetch('/api/lookups');
            let { categories } = await resp.json(); 
           
            let parsedCats = categories.map((cat:any)=&gt;{
               return {
                    value : cat.name,
                    label : cat.name
                }
            })
            setCatOptions(parsedCats);
        })()
    },[])

  return ( 
        catOptions ? 
        &lt;MultiSelect
            mb="sm"
            label="Categories"
            data={catOptions}
            placeholder="Select or type categories"
            searchable
            creatable
            getCreateLabel={(query) =&gt; `+ Create ${query}`}
            onCreate={(query) =&gt; { 
                const item = { value: query, label: query };
                setCatOptions((current:any) =&gt; [...current, item]);
                return item;
            }}
            /&gt;
         : null 
  );
}
export default CategorySelect;</code></pre>



<p>Above will set up our input to have data. As soon as you focus &#8211; you will see the list appear in the bottom. And as soon as you start typing &#8211; and what you typed is not in the list, a &#8220;Create XXX&#8221; appears in the bottom &#8211; all you have to do is select it. </p>



<p>How cool is that!</p>



<h3 class="wp-block-heading">Inserting, Updating and Deleting Records</h3>



<p>Now back to our API, we will add the logic that will allow us to insert, update and remove records. Remember, we only have an array of strings &#8211; so we are writing our logic based on that. </p>



<pre class="wp-block-code"><code lang="typescript" class="language-typescript"> try{
        const dataFromPost : string[]= req.body.data; 
        const dishId = req.body.id;
        
        //FIRST FIND CATIDS FROM ARRAY OF STRINGS 

        const foundData = await prisma?.category.findMany({
            where : {
               name : { in: dataFromPost }
            }
        }) as Categories[];

        const foundDataStr : string[] = [];
        let newEntry : string[] = [];
        let entryIds : number[] = []; 
        
        foundData?.map((item)=&gt;{
            entryIds.push(item.id);
            foundDataStr.push(item.name);
        })
        
        //PUT NEW CATEGORIES TO BE INSERTED IN A TEMP ARRAY FOR NOW...
        newEntry = dataFromPost.filter((item)=&gt;!foundDataStr.includes(item))
        
        // CHECK IF CAT ID &amp;&amp; DISHID EXIST IN LOOKUP...

        const existingLookup = await prisma?.categoriesOnDishes.findMany({
            where : {
            dishId : dishId, 
            }
        })

        // ACTUAL CATS TO BE DELETED FROM LOOKUP
        let itemIdsToDelete : number[] = [];   
        
        // REMOVING CATS TO PREVENT DUPLICATE INSERT TO LOOKUP
        let itemIdsToRemove : number[] = [];  
        
        foundData?.forEach((item)=&gt;{
            if(!dataFromPost.includes(item.name)){
            itemIdsToDelete.push(item.id)
            }
        }) 
        
        existingLookup?.forEach((item : any)=&gt;{
            if(entryIds.includes(item[lookupItemIdKey])){
               itemIdsToRemove.push(item[lookupItemIdKey]);
            }else{
               itemIdsToDelete.push(item[lookupItemIdKey]);
            }
        })
        
        // REMOVE EXISTING LOOKUPS...     
        entryIds = entryIds.filter((id)=&gt;{
            return !itemIdsToRemove.includes(id);
        })
        type newEntryType = {
           name:string,
           userId:number, 
           description?:string, 
           default:boolean}

        // INSERT NEW CATEGORIES, ADD IDS TO CATIDS...
        if(newEntry.length &gt; 0){
            let newEntryObj : newEntryType[] = []; 
            newEntryObj = newEntry.map(item=&gt;{
            let obj : newEntryType= {
                name:item,          
                default : false           
            }
                return obj
            })
            const itemsInserted = await prisma?.category.createMany({ 
                data: newEntryObj, 
            })
            
            if(itemsInserted){
                const itemsInsertedResult = await prisma?.category.findMany({
                where : {
                userId : curUser.id, 
                name : { in: newEntry },
                }
            })
            
            let itemsInsertedIds : number[] = [];
            itemsInsertedResult?.forEach((item : any)=&gt;{
                itemsInsertedIds.push(item.id)
            })
            if(itemsInsertedIds){
                entryIds = entryIds.concat(itemsInsertedIds);
            }
            }   
        } //end if catsinserted...  
      
        
        //INSERT TO LOOKUP TABLE...
        const itemOnDishes = entryIds.map((item)=&gt;{
            return {
            dishId : dishId, 
            [lookupItemIdKey] : item
            }
        })

        //DOES NOT RETURN THE IDS!!!!
        await prisma?.categoryOnDishes.createMany({ 
            data: itemOnDishes, 
        }) 
        
        //DELETE ITEMS FROM LOOKUP
        if(itemIdsToDelete.length &gt; 0){
            await prisma?.categoryOnDishes.deleteMany({
               where: {
                 categoryId :{ in: itemIdsToDelete }, 
                 dishId : dishId
               },
            })
        }      
        return res.status(200).json({ success: true}) 

}catch(err){
    return res.status(500).json({ error: JSON.stringify(err)})  
}</code></pre>



<p>A lot going on here. First we check if categories exist in our category table. If it does, let&#8217;s save the ids in a temp array. We are also saving the ones that are not in the table &#8211; these are the &#8220;new items&#8221; that we have to insert. </p>



<p>We&#8217;re also figuring out which ones are existing in the lookup table &#8211; which is not found in the submitted array of strings. These are the lookups we have to delete. </p>



<p>Finally, we are simply returning &#8220;success : true&#8221; for now. Ideally, you will return the ids of the records you&#8217;ve updated. But at the time of writing, one of Prisma&#8217;s methods &#8211; specifically <em>createMany()</em> doesn&#8217;t return the ids. For the sake of simplicity &#8211; we just return &#8220;true&#8221;.  </p>



<h3 class="wp-block-heading">Back to the Component</h3>



<p>Okay, back to the front &#8211; let&#8217;s finish up our connect the dots. I&#8217;m only showing the necessary parts &#8211; that we need to add to our component. The comments below should show you how it works, and what its for. </p>



<pre class="wp-block-code"><code lang="typescript" class="language-typescript">//DONT FORGET THE STATE:
const [ selectedCats, setSelectedCats ] = useState([]);
const categoryChanged = (val:any) =&gt; {
        setSelectedCats(val);
    }
//THIS IS THE METHOD THAT CALLS OUR API...
const upsertMultiSelects = async (url:string, data:string[], id:number)=&gt;{        
        const options = {
            method: 'POST',
            ...getHeaders(null), 
            body : JSON.stringify({data,id})
        }
        const resp = await fetch(url, options)
        const res = await resp.json();
    }

//ADD THIS TO THE FORM SUBMIT HANDLER:

upsertMultiSelects(`/api/lookups`,selectedCats,result.id);


//ADD THIS TO THE COMPONENT PROPS:
value={selectedCats} 
onChange={categoryChanged}</code></pre>



<p>With all that in place, you can wire it up to your form&#8217;s submit function. This approach is a separate method to calling the updating of the lookup and category table. But you can of course &#8211; bunch it all up along with the rest of the fields on your form &#8211; into a single REST call.</p>



<h3 class="wp-block-heading">Final Result</h3>



<p>Now if all of that works, you should be able to save your changes. Remember, the front end will work the same as before &#8211; its the saving to the database &#8211; is what we went through.  </p>



<figure class="wp-block-image size-full"><img decoding="async" width="527" height="369" src="https://michaelsoriano.com/wp-content/uploads/2022/11/multiselect.gif" alt="" class="wp-image-7850"/></figure>



<p>Go ahead and save your form &#8211; and hit refresh. If all goes well, your data will be preserved &#8211; and you can continue with your day. </p>
<p>The post <a href="https://michaelsoriano.com/multi-select-input-mantine-prisma-nextjs/">Code a multi-select input with Mantine, Prisma and NextJS</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/multi-select-input-mantine-prisma-nextjs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Just in: SolidStart is in Beta &#8211; Now what to build?</title>
		<link>https://michaelsoriano.com/solidstart-is-in-beta-what-to-build/</link>
					<comments>https://michaelsoriano.com/solidstart-is-in-beta-what-to-build/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Sat, 12 Nov 2022 00:07:37 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7829</guid>

					<description><![CDATA[<p>A few days ago the people behind SolidJS released their meta-framework of their own called SolidStart. I think this is a major development for SolidJS. This is probably one of the biggest missing piece of the puzzle. Let me explain. Most front end developers know, React is king at the moment. There are many things [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/solidstart-is-in-beta-what-to-build/">Just in: SolidStart is in Beta &#8211; Now what to build?</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>A few days ago the people behind SolidJS <a href="https://www.solidjs.com/blog/introducing-solidstart">released</a> their <strong>meta-framework</strong> of their own called SolidStart. I think this is a major development for SolidJS. This is probably one of the biggest missing piece of the puzzle. </p>



<p>Let me explain. </p>



<p>Most front end developers know, React is king at the moment. There are many things to love about React, but there are also many things that <a href="https://marmelab.com/blog/2022/09/20/react-i-love-you.html">people don&#8217;t like</a>. But why stick to React? While there are countless alternatives out there like Svelte, VueJS, SolidJS? </p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-1024x667.jpg" alt="" class="wp-image-7836" width="733" height="477" srcset="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-1024x667.jpg 1024w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-300x195.jpg 300w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-1-768x500.jpg 768w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-1.jpg 1130w" sizes="(max-width: 733px) 100vw, 733px" /></figure>



<p>Well for me &#8211; its the ecosystem. There are thousands of components, design systems, plugins for React &#8211; that will make your development so much faster. A major feature is just an npm install away. </p>



<p>What&#8217;s one of the most important thing that is missing from Solid? It&#8217;s the meta framework. The ability to go &#8220;isomorphic&#8221; &#8211; combine server and client side in one codebase. The ability to write APIs, file based routing, caching &#8211; all the good stuff a full stack development environment has to offer. </p>



<p>A &#8220;<strong>NextJS</strong>&#8221; for Solid basically. </p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1024x992.jpg" alt="" class="wp-image-7830" width="706" height="683" srcset="https://michaelsoriano.com/wp-content/uploads/2022/11/image-1024x992.jpg 1024w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-300x291.jpg 300w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-768x744.jpg 768w, https://michaelsoriano.com/wp-content/uploads/2022/11/image-1536x1488.jpg 1536w, https://michaelsoriano.com/wp-content/uploads/2022/11/image.jpg 1602w" sizes="(max-width: 706px) 100vw, 706px" /></figure>



<p>As you can see, these are basically what NextJS can do. The simple fact that you no longer need another server to put your server side logic in &#8211; is a big win. Also, having the &#8220;fine grained&#8221; reactivity is what makes SolidJS so attractive. Also, fixing the stuff we&#8217;re not particularly crazy about in React.</p>



<h3 class="wp-block-heading">So what to build next? </h3>



<p>I am thinking of re-doing my <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/">Shopping Cart code</a> in SolidStart. If you think about it, an e-commerce website will always need to be &#8220;SEO&#8221; friendly. So you will need that HTML rendered by the server. I would also like to redo that in TypeScript.  </p>



<p>I was also considering a Job listing website. With features like &#8211; applicants can upload a PDF resume and it automatically pre-fills the required fields. For the database, I&#8217;ve been working with <a href="https://www.prisma.io/">Prisma</a> + PostgreSQL and have fallen in love with it &#8211; so I think I&#8217;ll stick with that. </p>



<p>I just wish there was more SolidJS design systems out there. Something like a <a href="https://mantine.dev/">Mantine</a> or <a href="https://chakra-ui.com/">Chakra</a> for SolidJS. If you guys know of any, please leave a comment below. </p>
<p>The post <a href="https://michaelsoriano.com/solidstart-is-in-beta-what-to-build/">Just in: SolidStart is in Beta &#8211; Now what to build?</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/solidstart-is-in-beta-what-to-build/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Let’s build a Shopping Cart website with SolidJS and Bootstrap – Part 2</title>
		<link>https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-2/</link>
					<comments>https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-2/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 04 Jul 2022 00:29:52 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7696</guid>

					<description><![CDATA[<p>In the previous post, we&#8217;ve completed setting up the frame for our shopping cart website. We&#8217;ve added the routes, finished the product listing page, added filters &#8211; and we&#8217;ve even started an empty shell for the cart component. Note that if you want to simply download the code &#8211; head on to Github. If you&#8217;d [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-2/">Let’s build a Shopping Cart website with SolidJS and Bootstrap – Part 2</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In the <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/">previous post</a>, we&#8217;ve completed setting up the frame for our shopping cart website. We&#8217;ve added the routes, finished the product listing page, added filters &#8211; and we&#8217;ve even started an empty shell for the cart component. </p>



<p>Note that if you want to simply download the code &#8211; head on to <a href="https://github.com/michaelsoriano/solidjs-shoppingcart">Github</a>. If you&#8217;d like to see the working demo, click the button below. </p>



<p class="btn"><a href="https://solidjs-shoppingcart.vercel.app/" target="_blank" rel="noreferrer noopener nofollow">View Demo </a></p>



<p>Otherwise, let&#8217;s continue from where we left off: </p>



<h3 class="wp-block-heading">Display a single Product</h3>



<p>So when clicking a product &#8211; all we get is a blank screen with the slug. Open the file <strong>Product.jsx</strong> and start by creating our signals. </p>



<pre title="Product.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { useParams } from "solid-app-router"
import { productList } from '../data/productList';

export default function Product(){
    const ALLPRODUCTS = productList.slice();
    const [ product, setProduct ] = createSignal({});
    const params = useParams();

    ... 
}</code></pre>



<p>First we&#8217;re importing our static list and creating a constant for us to use. We&#8217;re also creating a signal called product &#8211; which will hold the current focused product &#8211; depending on the slug from the url. </p>



<p>Let&#8217;s add an <em><strong>onMount()</strong></em> to show a single product. </p>



<pre title="Product.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx"> onMount(()=&gt;{
        let productArr = ALLPRODUCTS.filter((item)=&gt;{
            return item.slug === params.slug;
        })
        if(productArr.length === 0){
            alert('HANDLE ERROR');
        }else{
            setProduct(productArr[0])
        }        
 })</code></pre>



<p>All this does is setting up a single product on mount. We&#8217;re just alerting an error when a product is not found &#8211; we can improve this later. </p>



<p>We&#8217;re also going to add some options before adding items to the cart. This will be the &#8220;quantity&#8221; and the &#8220;size&#8221; of the product. </p>



<p>Still in <strong>Product.jsx</strong> &#8211; I&#8217;m just going to show the important parts below. I will omit the bootstrap HTML to save space. </p>



<pre title="Product.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { createSignal, For, onMount } from "solid-js";
import { Button, Card, Col, Container, Form, FormLabel, Row } from "solid-bootstrap";

export default function Product(){
  ...
  const [ selectedSize, setSelectedSize ] = createSignal('');
  const [ quantity, setQuantity ] = createSignal(1);
  const [ btnDisabled, setBtnDisabled ] = createSignal(true);
  ...
  return (
        &lt;Container class="mb-5 mt-5 row inner-wrap"&gt;        
           ...
            &lt;Form.Select name="size" value={selectedSize()} onChange={changeHandler}&gt;                        
                 &lt;For each={product().sizes}&gt;
                   {size=&gt;&lt;option value={size}&gt;{size}&lt;/option&gt;}
                 &lt;/For&gt;
                 &lt;/Form.Select&gt;
           ... 
            &lt;Form.Select name="quantity" value={quantity()} onChange={changeHandler}&gt;
           ...
           &lt;/Form.Select&gt;    
           ...        
           &lt;Button disabled={btnDisabled()} value={product().id} onclick={addToCart}&gt;Add to Cart&lt;/Button&gt;                    
        &lt;/Container&gt;       
    )</code></pre>



<p>So we&#8217;re adding more signals &#8211; for the two input fields that we need &#8211; which is the size and quantity. And since both are required fields, we&#8217;re setting the Button to disabled first, then when both values are not empty &#8211; we enable it. We do this by adding a &#8220;createEffect()&#8221;: </p>



<pre title="Product.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">...
createEffect(()=&gt;{
        if(selectedSize() !== '' &amp;&amp; quantity() !== ''){
            setBtnDisabled(false);
        }else{
            setBtnDisabled(true);
        }
})</code></pre>



<p>Now take a look at our button and try changing the inputs: </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="727" height="509" src="https://michaelsoriano.com/wp-content/uploads/2022/07/button-disabled.gif" alt="" class="wp-image-7713"/></figure>



<h3 class="wp-block-heading"> Adding to Cart</h3>



<p>Let&#8217;s move on the <em>addToCart()</em> logic. Now adding is pretty straightforward &#8211; but let&#8217;s remember, you don&#8217;t want to keep pushing to the cart items array &#8211; because what if the item is already in there? In that case you want to just update it. </p>



<pre title="Product.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">function addToCart(){
        let productToAdd ={
             ...product(), 
            size : selectedSize(),
            quantity : quantity()
        
        }; 
        let items = cartItems.slice();
        let foundIndex, found;
        found = items.filter((item,ind)=&gt;{            
            if(item.id === productToAdd.id 
                &amp;&amp; item.size === productToAdd.size){
                    foundIndex = ind;
                    return item
                }
        })

        let msg = '';
        if(found.length &gt; 0){
            msg = 'Item updated in cart';
            let productToUpdate = {
                ...found[0], 
                quantity : productToAdd.quantity, 
                subtotal : productToAdd.quantity * productToAdd.price
            }
            items.splice(foundIndex, 1, productToUpdate); 
        }else{
            msg = 'Item added to cart';
            productToAdd.size = selectedSize();
            productToAdd.quantity = parseInt(quantity());
            productToAdd.subtotal = productToAdd.quantity * productToAdd.price;
            items.push(productToAdd);
        }
        setCartItems(items);
        setToastMessage(msg);
}</code></pre>



<p>A quick run down of what&#8217;s going on above, we&#8217;re simply rebuilding the cartItems array (which is a central store), so we can display it in our cart. As mentioned, we&#8217;re trying to see if an item is already in the cart &#8220;<strong>productToUpdate</strong>&#8221; by checking if its the same product and size. If it is, we&#8217;re simply updating the quantity and subtotal. If it&#8217;s not existing &#8220;<strong>productToAdd</strong>&#8220;, then we simply push to the array. </p>



<p>We&#8217;re also setting a toast message to display a small notification after they update the cart. </p>



<p>Really quick &#8211; let&#8217;s add a small bubble to the &#8220;<strong>Cart</strong>&#8221; link in our header. Remember how &#8220;<strong>cartItems</strong>&#8221; is accessible in all of our components? </p>



<pre title="Header.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { setShowCart, cartItems } from '../App';
...
&lt;Nav.Link class="cart-link" onClick={setShowCart(true)}&gt;Cart 
                    { cartItems.length &gt; 0 
                    ? &lt;span class="cart-item-indicator"&gt;{cartItems.length}&lt;/span&gt; 
                    : null }&lt;/Nav.Link&gt;</code></pre>



<p>So above is a simple span tag that shows up if there&#8217;s items in our cart. Note that I&#8217;ve stuffed the CSS in index.html for simplicity &#8211; just grab it from the repo. </p>



<p>Let&#8217;s see how it looks so far: </p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" src="https://michaelsoriano.com/wp-content/uploads/2022/07/toast-bubble.png" alt="our toast and bubble span" class="wp-image-7716" width="840" height="504" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/toast-bubble.png 855w, https://michaelsoriano.com/wp-content/uploads/2022/07/toast-bubble-300x180.png 300w, https://michaelsoriano.com/wp-content/uploads/2022/07/toast-bubble-768x462.png 768w" sizes="(max-width: 840px) 100vw, 840px" /></figure>



<p>Let&#8217;s now move on to our Cart component and display our items.</p>



<h3 class="wp-block-heading">Display Cart Items</h3>



<p>Remember in <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/">Part 1</a> &#8211; we&#8217;ve created an &#8220;<a href="https://solid-libs.github.io/solid-bootstrap/components/offcanvas">OffCanvas</a>&#8221; component called &#8220;<strong>Cart</strong>&#8220;? Let&#8217;s add some code to it that will show us our cart items. First, let&#8217;s import <em>cartItems </em>and let&#8217;s create a signal for the total. We&#8217;re also going to create an effect &#8211; so that every time <em>cartItems </em>change, our total reacts with it.</p>



<pre title="Cart.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { createEffect, createSignal, For } from "solid-js";
import { cartItems } from "./App";
...
const [total, setTotal ] = createSignal(0);
...

export default function Cart(){
    createEffect(()=&gt;{
        let ttl = 0;
        cartItems.forEach((item)=&gt;{
            ttl = ttl+item.subtotal;
        })      
        setTotal(ttl);
    })
}</code></pre>



<p>The HTML simply loops through our <em>cartItems</em> and shows the details of each cart item:</p>



<pre title="Cart.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">&lt;For each={cartItems}&gt;
            {(product)=&gt;{
                return (
                    &lt;Row class="mb-4"&gt;
                        &lt;Col xs="3"&gt;
                            &lt;Image src={product.image} class='thumbnail' /&gt; 
                        &lt;/Col&gt;
                        &lt;Col xs="9" class="cart-item-text"&gt;
                            &lt;h6&gt;{product.name}&lt;/h6&gt;
                            &lt;p&gt;&lt;span&gt;{product.size}&lt;/span&gt;&lt;/p&gt;
                            &lt;p class="price-row"&gt;
                                &lt;span&gt;${product.price.toFixed(2)} (x{product.quantity})&lt;/span&gt;
                                &lt;span&gt;${product.subtotal.toFixed(2)}&lt;/span&gt;
                            &lt;/p&gt;
                        &lt;/Col&gt;    
                    &lt;/Row&gt; 
                )
            }}
        &lt;/For&gt;</code></pre>



<p>Note that there are optimal ways to handle the calculation of the totals. For instance, we&#8217;re simply doing a &#8220;<em>toFixed()</em>&#8221; &#8211; to make the display of the totals better. But in reality, you&#8217;d want to calculate decimals etc. Again, we&#8217;re keeping it simple for now. </p>



<p>Let&#8217;s see how our cart looks. </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="812" height="537" src="https://michaelsoriano.com/wp-content/uploads/2022/07/cart-demo.gif" alt="Cart Demo" class="wp-image-7726"/></figure>



<h3 class="wp-block-heading">Edit / Remove Cart Items</h3>



<p>Finally, let&#8217;s look at the cart experience. You&#8217;d want to let your users edit the cart items directly. Most likely, the ability to adjust the quantity of an item &#8211; and of course, remove it entirely. </p>



<p>In our CartItems component, let&#8217;s add the buttons in the HTML. </p>



<pre title="CartItems.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">&lt;button  value={ind()} onClick={evt=&gt;removeItem(evt)}&gt;x&lt;/button&gt;
...
&lt;span&gt;
    &lt;button value={ind()} onClick={evt=&gt;updateQuantity(evt,'add')}&gt;+&lt;/button&gt;
      {product.quantity}
    &lt;button value={ind()} onClick={evt=&gt;updateQuantity(evt,null)}&gt;-&lt;/button&gt;
&lt;/span&gt;
</code></pre>



<p>Notice the two handlers that we&#8217;ve attached the buttons with (updateQuantity and removeItem) &#8211; we&#8217;ll get to that in a bit. </p>



<p>Let&#8217;s add a bit of styling to our newly added buttons. </p>



<pre class="wp-block-code"><code lang="css" class="language-css"> .cart-item-text button {
        border: 1px solid #ccc;
        color: #0a0909;       
        border-radius: 4px;
        margin-left: 5px;
        margin-right: 5px;
        font-size: 12px;
        height: 16px;     
        line-height: 9px;
        padding-bottom: 2px;
} </code></pre>



<p>Taking a quick look at how our buttons look &#8211; I say its not too shabby eh? </p>



<p>Now clicking on each button doesn&#8217;t do anything yet. Let&#8217;s fix that.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="717" height="514" src="https://michaelsoriano.com/wp-content/uploads/2022/07/cart-buttons.png" alt="Buttons added" class="wp-image-7740" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/cart-buttons.png 717w, https://michaelsoriano.com/wp-content/uploads/2022/07/cart-buttons-300x215.png 300w" sizes="(max-width: 717px) 100vw, 717px" /></figure>



<p>Let&#8217;s start by creating the <strong>updateQuantity()</strong> function: </p>



<pre title="CartItems.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">function updateQuantity(evt,method){
     evt.preventDefault();
     const index = parseInt(evt.target.value);         
     let temp = cartItems.map((item,i)=&gt;{
         if(index === i){
             if(item.quantity === 1 &amp;&amp; !method){
                 return {...item};
             }
             const qty = method === 'add' ? item.quantity + 1 : item.quantity - 1;
             const subtotal = item.price * qty;
             return {
                 ...item,
                 quantity : qty, 
                 subtotal : subtotal
             }
         }else{
             return {...item};
         }            
     })
     setCartItems(temp);     
}</code></pre>



<p>Going through the code above, first &#8211; we prevent default to stop the default behavior of the button. Then we grab the index of the clicked item, so we know which item in the <em>cartItems </em>array will be updated. </p>



<p>Now we do everything inside a <em>map()</em> function. We&#8217;re basically checking if its the right index, otherwise, we simply return the item. If it is the right index &#8211; we do our calculation. Depending if the operation is a &#8220;sum&#8221; &#8211; we increment, or decrement if its not.  </p>



<p>Finally, let&#8217;s build the removeItem() function: </p>



<pre title="CartItem.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">function removeItem(evt){
     evt.preventDefault();
     const index = parseInt(evt.target.value);    
     let items = [...cartItems]; 
     items.splice(index,1)
     setCartItems(items);
 }</code></pre>



<p>This function is pretty simple. We just do a splice &#8211; for the clicked index to remove it from the array. </p>



<p>Below shows how our newly created buttons behave:</p>



<figure class="wp-block-image size-full border"><img decoding="async" width="854" height="531" src="https://michaelsoriano.com/wp-content/uploads/2022/07/cart-buttons-demo.gif" alt="buttons in action" class="wp-image-7742"/></figure>



<p>You can see, everything is reacting to our updates accordingly. Not only the quantity, as well as the subtotals and the total. </p>



<h3 class="wp-block-heading">Conclusion</h3>



<p>There you have it. A simple Shopping Cart application built on SolidJS and Bootstrap. Hopefully by going through this tutorial, you can truly see how SolidJS&#8217;s reactivity works. </p>



<p>So what&#8217;s the verdict? Is SolidJS better than React? </p>



<p>I think it is. </p>



<p>It is definitely a lot cleaner and much more intuitive to write. I am glad that they kept the good parts of React, and addressed the most annoying parts. I hope to see a lot more SolidJS in the future. </p>



<p>What&#8217;s your experience with Solid? Leave your comments below. </p>
<p>The post <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-2/">Let’s build a Shopping Cart website with SolidJS and Bootstrap – Part 2</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-2/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Let&#8217;s build a Shopping Cart website with SolidJS and Bootstrap &#8211; Part 1</title>
		<link>https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/</link>
					<comments>https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 27 Jun 2022 04:21:39 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7610</guid>

					<description><![CDATA[<p>So it&#8217;s been a while since I&#8217;ve posted a tutorial. I have been stagnant for a while, just using the same technologies for work and personal projects. Although recently, one framework caught my eye &#8211; SolidJS. It claims to have &#8220;true&#8221; reactivity and addresses many of the things I don&#8217;t like about React (such as [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/">Let&#8217;s build a Shopping Cart website with SolidJS and Bootstrap &#8211; Part 1</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>So it&#8217;s been a while since I&#8217;ve posted a tutorial. I have been stagnant for a while, just using the same technologies for work and personal projects. Although recently, one framework caught my eye &#8211; <a href="https://www.solidjs.com/" data-type="URL" data-id="https://www.solidjs.com/">SolidJS</a>. It claims to have &#8220;<em>true</em>&#8221; reactivity and addresses many of the things I don&#8217;t like about React (<em>such as too much unnecessary re-renders</em>). </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="683" height="268" src="https://michaelsoriano.com/wp-content/uploads/2022/07/image.png" alt="SolidJS caption" class="wp-image-7737" title="" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/image.png 683w, https://michaelsoriano.com/wp-content/uploads/2022/07/image-300x118.png 300w" sizes="(max-width: 683px) 100vw, 683px" /></figure>



<p>Now don&#8217;t get me wrong &#8211; I like React. I think functional components, JSX, hooks &#8211; are all good things. But there are a few quirks that I wish was different. </p>



<p class="btn btn-small"><a href="https://solidjs-shoppingcart.vercel.app/" target="_blank" rel="noreferrer noopener nofollow">View Demo</a></p>



<p>I recommend going through Solid&#8217;s website and finding out for yourself. I&#8217;ve also decided to use Bootstrap for the CSS framework because its what&#8217;s available. Note that there are hardly any pre-built CSS components available for Solid at time of writing. I do hope this will change in time &#8211; because I honestly like Solid so far.  </p>



<p>So let&#8217;s give this a go. We&#8217;re building a shopping cart website. One with a product listing page, complete with filters. We&#8217;ll add a single product page and a global store where the cart lives. And finally, we&#8217;ll add routes so we can access parts of the application through a bookmarkable url. </p>



<p>Here&#8217;s a quick preview of what we&#8217;re building:</p>



<figure class="wp-block-image size-full border"><img decoding="async" width="854" height="628" src="https://michaelsoriano.com/wp-content/uploads/2022/07/shopping-cart-app.gif" alt="shopping cart app in solidjs" class="wp-image-7732"/></figure>



<p>Ready to start? Let&#8217;s begin.  </p>



<h3 class="wp-block-heading">Setting things up</h3>



<p>Note that I will skip the installation parts &#8211; simply clone and run <strong>npm install</strong>. The Github repository found <a href="https://github.com/michaelsoriano/solidjs-shoppingcart">here</a>. You can also checkout the demo which can be accessed through this <a href="https://solidjs-shoppingcart.vercel.app/">link</a>. </p>



<p>Let&#8217;s start with the routes. We&#8217;re going to keep things simple &#8211; with just 2 routes: <strong>Products </strong>and <strong>Product</strong>. The products (<em>which is also the homepage</em>) simply lists all the products we have, and the Product &#8211; will show the product detail when clicked. </p>



<p>In <strong>index.jsx</strong>, let&#8217;s wrap our App inside a Router component:</p>



<pre title="index.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { render } from 'solid-js/web';
import { Router } from 'solid-app-router';
import App from './App';

render(
    () =&gt; 
        ( &lt;Router&gt;
         &lt;App /&gt;
       &lt;/Router&gt; ), document.getElementById('root'));</code></pre>



<p>Now let&#8217;s move on to <strong>App.jsx</strong>. Let&#8217;s add the two routes that we talked about:</p>



<pre title="App.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { lazy } from "solid-js";
import { Routes,Route } from 'solid-app-router';
import { Container } from "solid-bootstrap";

const Product = lazy(() =&gt; import("./routes/Product"));
const Products = lazy(() =&gt; import("./routes/Products"));

function App() {
  return (
    &lt;Container class="pb-5"&gt;      
      &lt;Routes&gt;
        &lt;Route path='/' element={&lt;Products /&gt;}   /&gt;
        &lt;Route path="/:slug" element={&lt;Product /&gt;} /&gt;
      &lt;/Routes&gt;
    &lt;/Container&gt;
  );
}
export default App;</code></pre>



<p>Let&#8217;s also go ahead and create a folder called &#8220;<em>routes</em>&#8221; and add two components inside it. Name them <em>Products.jsx</em> and <em>Product.jsx</em></p>



<pre title="Products.jsx and Product.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">//this is Products.jsx:
export default function Products(){
    return (
        &lt;div class="products-page mb-5 mt-5 row"&gt;
        &lt;h3 class="mb-5"&gt;Products&lt;/h3&gt;
        &lt;div class="col-md-3"&gt;
            Filters
        &lt;/div&gt;         
        &lt;div class="col-md-9 d-flex flex-wrap gap-4"&gt;        
            Product List     
        &lt;/div&gt;       
        &lt;/div&gt;
    )
}
//this is Product.jsx:
import { useParams } from "solid-app-router"
import { Container } from "solid-bootstrap";

export default function Product(){
    const params = useParams();
    return (
        &lt;Container class="inner-wrap  mb-5 mt-5 row"&gt;
            &lt;h3 class="mb-5"&gt;Single product - slug: {params.slug}&lt;/h3&gt;
        &lt;/Container&gt;       
    )
}</code></pre>



<p>Not a lot going on here, but we&#8217;ve setup our website with the minimum routes necessary. Let&#8217;s see what we have so far: </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="712" height="376" src="https://michaelsoriano.com/wp-content/uploads/2022/06/setting-up-1.gif" alt="" class="wp-image-7673"/></figure>



<p>Let&#8217;s also add a header and footer &#8211; to make our website look nicer. Note that the header and footer code are all boilerplate code from Bootstrap &#8211; so don&#8217;t pay too much attention to them. Just keep note of the &#8220;<em>Cart</em>&#8221; button in the header &#8211; we&#8217;ll use this to hide/show our cart.</p>



<pre title="Header.jsx and Footer.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">//this is Header.jsx
import logo from '../logo.svg';
import { Link } from 'solid-app-router';
import { Navbar, NavDropdown, Nav, Container } from 'solid-bootstrap';

function Header(){
    return (
        &lt;Navbar collapseOnSelect expand="lg" bg="dark" variant="dark"&gt;
            &lt;Container&gt;
            &lt;Navbar.Brand&gt;
            &lt;Link href='/' class="no-underline color-white"&gt;
                &lt;img class="me-2" src={logo} width="30" height="28" alt="logo" /&gt;
                Shopping Demo
            &lt;/Link&gt;            
            &lt;/Navbar.Brand&gt;
            &lt;Navbar.Toggle aria-controls="responsive-navbar-nav" /&gt;
            &lt;Navbar.Collapse id="responsive-navbar-nav"&gt;                
                &lt;Nav&gt;
                &lt;Nav.Link&gt;Cart&lt;/Nav.Link&gt;
                &lt;/Nav&gt;
            &lt;/Navbar.Collapse&gt;
            &lt;/Container&gt;
        &lt;/Navbar&gt;
    )
} 
export default Header;

//this is footer
import { Container } from "solid-bootstrap";

export default function Footer(){
    return (
        &lt;footer&gt;
            &lt;Container&gt;Solid JS works!&lt;/Container&gt;
        &lt;/footer&gt;
    );
}</code></pre>



<p>Now things are starting to shape up. </p>



<figure class="wp-block-image size-full"><img decoding="async" width="839" height="410" src="https://michaelsoriano.com/wp-content/uploads/2022/07/header-footer.png" alt="" class="wp-image-7700" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/header-footer.png 839w, https://michaelsoriano.com/wp-content/uploads/2022/07/header-footer-300x147.png 300w, https://michaelsoriano.com/wp-content/uploads/2022/07/header-footer-768x375.png 768w" sizes="(max-width: 839px) 100vw, 839px" /></figure>



<p>Now that our website frame is in place, we can start filling it up with some data and add some structure. </p>



<h3 class="wp-block-heading">Add the Products</h3>



<p>For our demo purposes, we&#8217;re just going to add static data to populate our products. You will probably add yours from an API of some sort. For now, add a static file called <strong>productList.js</strong> &#8211; with an array of objects like so: </p>



<pre title="productList.js" class="wp-block-code"><code lang="javascript" class="language-javascript">[
 {
        id: 'prod_LbfpnuB1dc81pW',
        description : 'Lorem ipsum dolor sit amet...',
        name: 'Black Jacket',
        price: 50,
        currency: 'USD',
        image: 'https://images.unsplash.com...',
        slug : 'black-jacket', 
        category : ['Formal','Casual']
    },
    ...
]</code></pre>



<p>Now back in <strong>App.jsx</strong> let&#8217;s create a store for our products and add the product list above: </p>



<pre title="App.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { productList } from "./data/productList";

...

export const [products,setProducts] = createStore(productList);</code></pre>



<p>We&#8217;ve added this to <strong>App.jsx</strong> and exported it &#8211; so we can use our products globally. You can choose to add this store into a separate file &#8211; but for the sake of simplicity, I just added it here. </p>



<p>Now let&#8217;s display the products in our HTML. </p>



<pre title="Products.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { For } from "solid-js";
import { products } from "../App";
import { useNavigate } from "solid-app-router";
import { Button, Card, Col } from "solid-bootstrap";

function ProductTile({product}){
    const navigate = useNavigate();
    return (
         &lt;Col class="col-md-3"&gt;
            &lt;Card&gt;
            &lt;Card.Img variant="top" src={product.image} /&gt;
            &lt;Card.Body&gt;
                &lt;Card.Title&gt;{product.name}&lt;/Card.Title&gt;
                &lt;Card.Text class="lt-clamp-3"&gt;
                    {product.description}
                &lt;/Card.Text&gt;
                &lt;Button variant="primary" onclick={()=&gt;{navigate(`/${product.slug}/`)}}&gt;Details&lt;/Button&gt;
            &lt;/Card.Body&gt;
            &lt;/Card&gt;             
         &lt;/Col&gt;
    )
}

export default function Products(){
    return (
        &lt;div class="products-page mb-5 mt-5 row"&gt;
        &lt;h3 class="mb-5"&gt;Products&lt;/h3&gt;
        &lt;div class="col-md-3"&gt;
            Filters
        &lt;/div&gt;         
        &lt;div class="col-md-9 d-flex flex-wrap gap-4"&gt;        
        &lt;For each={products}&gt;            
            {product =&gt; &lt;ProductTile product={product} /&gt; }
        &lt;/For&gt;         
        &lt;/div&gt;       
        &lt;/div&gt;
    )
}</code></pre>



<p>A few things to note in the code above. Notice the &#8220;For&#8221; component. This is specific to how Solid does it&#8217;s for loops in JSX. Although you can still use a <strong>.map()</strong> &#8211; but I thing having this is much cleaner. </p>



<p>Now try clicking the &#8220;<em>details</em>&#8221; and it should route to our single page.</p>



<figure class="wp-block-image size-full border"><img decoding="async" width="918" height="516" src="https://michaelsoriano.com/wp-content/uploads/2022/06/setting-up-2.gif" alt="" class="wp-image-7676"/></figure>



<h3 class="wp-block-heading">Add Product Filters</h3>



<p>Let&#8217;s add a simple filter mechanism for our products. If you notice in our fake data, each product has a category node &#8211; which is an array of categories. From this we can build our filters. </p>



<p>Let&#8217;s create another component called <strong>Filters.jsx</strong>. In it, add the following code:</p>



<pre title="Filters.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { createSignal, onMount } from "solid-js";
import { productList } from "../data/productList";
export default function Filters(){
    
    const ALLPRODUCTS = productList.slice(); //making copy so doesnt mutate
    const [filters,setFilters] = createSignal([]); 
   
    return (
        &lt;For each={filters()}&gt;
        {(filter)=&gt;{               
            return (
                &lt;div class="form-check"&gt;
                &lt;input class="form-check-input" 
                    type="checkbox" 
                    value={filter.name} 
                    id={filter.name} 
                    checked={filter.checked} 
                     /&gt;
                &lt;label class="form-check-label" for={filter.name}&gt;
                    {filter.name}
                &lt;/label&gt;
                &lt;/div&gt;
            )
        }}
        &lt;/For&gt;
    )
}</code></pre>



<p>Okay so a few things going on in this file. First, notice that we&#8217;re bringing in the static list of products &#8211; we&#8217;re assigning it to a constant &#8220;<strong>ALLPRODUCTS</strong>&#8221; for later use. Also, note the signal we&#8217;ve created by using <strong>createSignal()</strong>. This is basically equivalent to React&#8217;s useState(). This is how things become reactive. </p>



<p>Notice that we have 2 contsants, &#8220;<em>filters</em>&#8221; and &#8220;<em>setFilters</em>&#8221; &#8211; which is basically a getter and a setter. We&#8217;re setting it to an empty array for now. </p>



<p>Add an <strong>onMount()</strong> function &#8211; to build our filters and set it using our setter.</p>



<pre title="Filters.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx"> onMount(()=&gt;{
        let filterList = [];
        ALLPRODUCTS.forEach((product)=&gt;{
            product.category.forEach((cat)=&gt;{
                let found = filterList.some(function(el) {
                    return el.name === cat;
                });
                if(!found){
                    filterList.push({name:cat,checked:false});
                }                
            })
        })     
        setFilters(filterList); 
    })</code></pre>



<p>I really like Solid&#8217;s <strong>onMount()</strong> lifecycle hook &#8211; which is equivalent to React&#8217;s useEffect() with no dependencies. So it basically just runs once (on mount) &#8211; and it <span style="text-decoration: underline;">really only runs once</span> (not like <a href="https://stackoverflow.com/questions/60618844/react-hooks-useeffect-is-called-twice-even-if-an-empty-array-is-used-as-an-ar">useEffect()</a>). So inside this hook, we&#8217;re looping through the product categories and creating a unique array of objects out of it. </p>



<p>Each object is looped through our JSX &#8211; building our checkboxes like below: </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="763" height="429" src="https://michaelsoriano.com/wp-content/uploads/2022/07/filters-in-place.png" alt="" class="wp-image-7701" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/filters-in-place.png 763w, https://michaelsoriano.com/wp-content/uploads/2022/07/filters-in-place-300x169.png 300w" sizes="(max-width: 763px) 100vw, 763px" /></figure>



<p>Of course, nothing happens yet when you click it &#8211; that&#8217;s because we haven&#8217;t written the handler for it yet.</p>



<p>Add the following code for our click handler:</p>



<pre title="Filters.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">function filterChangeHandler(evt){
        setFilters(
            filters().map((item)=&gt;{
                return item.name === evt.target.value ? {...item,checked : evt.target.checked} : {...item}; 
            })
        );
        return false;
 }

...

//on the checkbox input add this:
onChange={filterChangeHandler}
//it should look like this:
&lt;input class="form-check-input" 
                    type="checkbox" 
                    value={filter.name} 
                    id={filter.name} 
                    checked={filter.checked} 
                    onChange={filterChangeHandler} /&gt;</code></pre>



<p>Now upon clicking &#8211; it really doesn&#8217;t do anything yet, it just updates our &#8220;filters&#8221; array to mark which categories are &#8220;checked&#8221;. So if you console log our filters array &#8211; it should look like below: </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="497" height="267" src="https://michaelsoriano.com/wp-content/uploads/2022/06/image-8.png" alt="" class="wp-image-7682" srcset="https://michaelsoriano.com/wp-content/uploads/2022/06/image-8.png 497w, https://michaelsoriano.com/wp-content/uploads/2022/06/image-8-300x161.png 300w" sizes="(max-width: 497px) 100vw, 497px" /></figure>



<p>Our filters array are now being updated &#8211; with the checkboxes that we&#8217;ve clicked. Now let&#8217;s update the DOM with the information we have. We do that by using &#8220;<strong>createEffect()</strong>&#8220;. </p>



<pre title="Filters.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">//add another import: 
import { setProducts } from "../App";

//add this to the component:
createEffect(() =&gt; {
        let filterArr = []; 
        filters().forEach((item)=&gt;{
            if(item.checked){
                filterArr.push(item.name);
            }
        }) 

        if(filterArr.length === 0){       
            setProducts(ALLPRODUCTS);
        }else{
            let filteredProducts = ALLPRODUCTS.filter((item)=&gt;{
                let found = item.category.some((cat)=&gt;{
                    return filterArr.includes(cat);
                });
                if(found){
                    return item;
                }
            })
            setProducts(filteredProducts);
        }

    });</code></pre>



<p>So effects are what&#8217;s know as &#8220;observers&#8221; in Solid. We use <strong>createEffect()</strong> &#8211; to track changes in our signals. Again, its the same as <em>useEffect</em> in React &#8211; but with a few notable differences. One in particular is not having to list the dependencies &#8211; which is quite annoying. Solid&#8217;s createEffect &#8211; simply knows what signals to observe.</p>



<p>So in our example, we&#8217;re really tracking changes in our filters array. It changes on mount, and every time we click the checkboxes. </p>



<p>So every time they change &#8211; we &#8220;react&#8221; by changing the listed products. </p>



<figure class="wp-block-image size-full border"><img decoding="async" width="932" height="715" src="https://michaelsoriano.com/wp-content/uploads/2022/06/setting-up-3.gif" alt="Filters are now working" class="wp-image-7683"/></figure>



<p>As you can see, our products are really starting to shape up. We can of course do a little more by adding a search and paging &#8211; but let&#8217;s keep it simple for now. </p>



<h3 class="wp-block-heading">Add the Cart Component</h3>



<p>Let&#8217;s wrap it up by adding a Cart component. It won&#8217;t contain logic yet, but more of a placeholder for the contents of our shopping cart. Create a <strong>Cart.jsx</strong> component and simply add the HTML below:</p>



<pre title="Cart.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">import { Offcanvas } from "solid-bootstrap";
import { showCart, setShowCart } from "./App";

export default function Cart(){  
    return (
        &lt;&gt;
        &lt;Offcanvas
            show={showCart()}
            onHide={()=&gt;{setShowCart(false)}}
            placement={'end'}&gt;
            &lt;Offcanvas.Header closeButton&gt;
                &lt;Offcanvas.Title&gt;Shopping Cart&lt;/Offcanvas.Title&gt;
            &lt;/Offcanvas.Header&gt;
            &lt;Offcanvas.Body&gt;
                Some text as placeholder.
            &lt;/Offcanvas.Body&gt;
            &lt;/Offcanvas&gt;
        &lt;/&gt;
    )
}</code></pre>



<p>We&#8217;re using &#8220;Offcanvas&#8221; from react bootstrap &#8211; which is a sliding sidebar component. Notice we&#8217;re passing two props (showCart and setShowCart) &#8211; which we&#8217;re adding as a global state. </p>



<p>Let&#8217;s go back to <strong>App.jsx</strong> and export the signals and include the component we just created:</p>



<pre title="App.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">//import cart
const Cart = lazy(() =&gt; import("./Cart"));

//add signal
export const [showCart,setShowCart] = createSignal(false);

//add the component
&lt;Cart /&gt;</code></pre>



<p>Now, to show and hide the cart, we should be able to do it from any component in the application. Obviously &#8211; we&#8217;ll have an &#8220;add to cart&#8221; in the products section, but we&#8217;re not there yet. </p>



<p>For now, let&#8217;s add it to <strong>Header.jsx</strong> &#8211; so we can have a static &#8220;<em>Cart</em>&#8221; link for easy access. </p>



<pre title="Header.jsx" class="wp-block-code"><code lang="jsx" class="language-jsx">//import our setter
import { setShowCart } from '../App';

//add as a handler to the click 
&lt;Nav.Link onClick={setShowCart(true)}&gt;Cart&lt;/Nav.Link&gt;</code></pre>



<p>Now when you click on the &#8220;Cart&#8221; link in the header, you should see our Cart component slide in and out</p>



<figure class="wp-block-image size-full border"><img decoding="async" width="774" height="676" src="https://michaelsoriano.com/wp-content/uploads/2022/06/setting-up-4.gif" alt="Cart component shows and hides" class="wp-image-7686"/></figure>



<p>Okay time to stop for now. I think we&#8217;ve made good progress. If you want to capture the code at this point of the tutorial, I&#8217;ve created a tag named <a href="https://github.com/michaelsoriano/solidjs-shoppingcart/releases/tag/part-1">part-1</a>. </p>



<p>Stay tuned for Part 2. </p>
<p>The post <a href="https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/">Let&#8217;s build a Shopping Cart website with SolidJS and Bootstrap &#8211; Part 1</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/lets-build-a-shopping-cart-website-with-solidjs-and-bootstrap-part-1/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Common JavaScript snippets for data manipulation</title>
		<link>https://michaelsoriano.com/common-javascript-snippets-for-data-manipulation/</link>
					<comments>https://michaelsoriano.com/common-javascript-snippets-for-data-manipulation/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Tue, 17 May 2022 19:08:57 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=7605</guid>

					<description><![CDATA[<p>I find myself having to look up how to do things in JavaScript. After years of doing so, I&#8217;ve realized that its pretty much a common set of techniques that look for when manipulating data. So I&#8217;ve decided to create this list. Note that this is by far not a complete list &#8211; and is [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/common-javascript-snippets-for-data-manipulation/">Common JavaScript snippets for data manipulation</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I find myself having to look up how to do things in JavaScript. After years of doing so, I&#8217;ve realized that its pretty much a common set of techniques that look for when manipulating data. So I&#8217;ve decided to create this list. Note that this is by far not a complete list &#8211; and is one that will continue to grow. </p>



<figure class="wp-block-image size-full"><img decoding="async" width="672" height="323" src="https://michaelsoriano.com/wp-content/uploads/2022/07/javascript.jpg" alt="JavaScript" class="wp-image-7761" srcset="https://michaelsoriano.com/wp-content/uploads/2022/07/javascript.jpg 672w, https://michaelsoriano.com/wp-content/uploads/2022/07/javascript-300x144.jpg 300w" sizes="(max-width: 672px) 100vw, 672px" /></figure>



<p>So here are common JS snippets for data manipulation: </p>



<h3 class="wp-block-heading">Find Unique Values from Array</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">// using SET:
let uniqueArr = [... new Set(arr)];     // MAKES NEW ARRAY
let uniqueObj = new Set(arr); 		// MAKES NEW OBJ

// not using SET 
let uniqueArray = arr.filter(function(item, pos) {
    return arr.indexOf(item) === pos;
})</code></pre>



<h3 class="wp-block-heading">Sorting Flat Arrays</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">arr.sort((a, b) =&gt; a - b);  // WILL SORT ASC 
arr.sort((a, b) =&gt; b - a);  // WILL SORT DESC
arr.sort()                  // WILL SORT STRINGS ASC </code></pre>



<h3 class="wp-block-heading">Sorting an Array of Objects</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">arr.sort((a,b)=&gt; a.prop - b.prop); //SORT BY VALUE OF .PROP IF NUMERIC
arr.sort((a,b) =&gt; (a.prop &gt; b.prop) ? 1 : ((b.prop &gt; a.prop) ? -1 : 0)); //SORT BY VALUE OF .PROP IF NOT NUMERIC</code></pre>



<h3 class="wp-block-heading">Sorting Objects by property value</h3>



<p>This is when you have a Map (or a hash table), and you want to sort by key.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">//obj is a map and you want to sort it by its property "sortProperty" and its a number 
Object.keys(obj).sort((a, b)=&gt; obj[a].sortProperty - obj[b].sortProperty);
//if "sortProperty" is string use:
Object.keys(obj).sort((a,b) =&gt; (a.sortProperty &gt; b.sortProperty) ? 1 : ((b.sortProperty &gt; a.sortProperty) ? -1 : 0));  </code></pre>



<h3 class="wp-block-heading">Find number of occurrences of an element in an Array</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">const arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
const counts = {};

for (const num of arr) {  //USE FOR OF
  counts[num] = counts[num] ? counts[num] + 1 : 1;
}
// WILL PRODUCE A MAP WITH ELEMENT (AS KEY), NUM OF OCCUR (AS VALUE)</code></pre>



<h3 class="wp-block-heading">Add/Subtract all numbers in an Array</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">let sum = arr.reduce((a, b) =&gt; a + b, 0); //ADD
let diff = arr.reduce((a, b) =&gt; a - b, 0); //SUBTRACT</code></pre>



<h3 class="wp-block-heading">Find Alphanumeric Chars from a String</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">'FT&amp;abC3'.match(/^[A-Za-z0-9]+$/) //WILL RETURN [F,T,a,b,C,3]</code></pre>



<h3 class="wp-block-heading">Object keys and values</h3>



<p>You don&#8217;t need to loop through objects to get an array of keys / values:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">Object.keys(obj) 			// GET KEYS OF OBJECT as an array
Object.values(obj) 			// GET VALUES OF OBJECT as an array 
Object.keys(obj).length 	        //FIND LENGTH OF OBJECT (NOT ARRAY) </code></pre>



<h3 class="wp-block-heading">Find Largest / Smallest number in Array:</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">Math.max(...arr);
Math.min(...arr);</code></pre>



<h3 class="wp-block-heading">Copy Arrays by value (not by reference)</h3>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">let arr1 = origArray.slice();  
let arr2 = origArray.slice();
//arr1 and arr2 are complete cloned copies of origArray</code></pre>



<p></p>
<p>The post <a href="https://michaelsoriano.com/common-javascript-snippets-for-data-manipulation/">Common JavaScript snippets for data manipulation</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/common-javascript-snippets-for-data-manipulation/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Create a File Uploader with React and WordPress REST API (Media)</title>
		<link>https://michaelsoriano.com/create-a-file-uploader-with-react-and-wordpress-rest-api-media/</link>
					<comments>https://michaelsoriano.com/create-a-file-uploader-with-react-and-wordpress-rest-api-media/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 08 Mar 2021 01:50:37 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=7312</guid>

					<description><![CDATA[<p>So I&#8217;m working on a small project and I ran into a task involving a form with a file input that has to update an image attached to a custom post type. It got pretty interesting because it took a bit of digging to get it to work. While there was not a lot of [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/create-a-file-uploader-with-react-and-wordpress-rest-api-media/">Create a File Uploader with React and WordPress REST API (Media)</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>So I&#8217;m working on a small project and I ran into a task involving a form with a file input that has to update an image attached to a custom post type. It got pretty interesting because it took a bit of digging to get it to work. While there was not a lot of examples of it online, and when there were some, they&#8217;re mostly using jQuery. So I decided it&#8217;s worthy of a little tutorial, and can come in handy in the future. </p>



<p>We&#8217;re using React, Axios and the Media endpoint in WordPress&#8217; REST API. First of, let&#8217;s see what we&#8217;re going to build: </p>



<figure class="wp-block-image size-large"><a href="https://michaelsoriano.com/wp-content/uploads/2021/03/file-upload.gif"><img decoding="async" width="775" height="612" src="https://michaelsoriano.com/wp-content/uploads/2021/03/file-upload.gif" alt="" class="wp-image-7314"/></a></figure>



<p>We&#8217;re not going in details on how the modal or the loading gif works. We&#8217;re really focusing on the file input and the events that happen when the &#8220;Update&#8221; button is clicked. </p>



<p>Read to get started? Let&#8217;s begin. </p>



<p>First, let&#8217;s import our modules. </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">import React, { useState, useRef } from "react";
import axios from 'axios';</code></pre>



<p>Let&#8217;s create a component called &#8220;ItemModal&#8221;, and add some HTML. </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">function ItemModal( { itemid } ){
    return (
        &lt;div&gt;
           {(()=&gt;{
              if(img){
                return (&lt;img src={img} alt='image' /&gt;)
              }
            })()}
           &lt;input id="imgUpload" type="file" ref={imgUpload} onChange={previewImage}/&gt;
           &lt;button onClick={updateItem}&gt;Update&lt;/button&gt;
        &lt;/div&gt;
    )
}</code></pre>



<p>Above is a simple component that shows an image coming from our local state, an input of type &#8220;file&#8221; with a &#8220;ref&#8221; (will explain later), and a button that updates our record. </p>



<p>Let&#8217;s add a couple of hooks.</p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">const imgUpload = useRef(null);
const [img, setImg] = useState('');</code></pre>



<p>We need both hooks to make our elements work. We use &#8220;useRef&#8221;, to create a reference to our file input in the DOM. Also an &#8220;img&#8221; state, so we can store the &#8220;URL&#8221; of the image we&#8217;re working with. </p>



<h3 class="wp-block-heading" id="the-update-item-method">The Update Item method</h3>



<p>The file input works almost out of the box. Upon clicking, the OS file explorer will popup and navigate through your local files so you can select. But actually getting that file to the WordPress is what this Update method will entail. </p>



<pre title="" class="wp-block-code"><code lang="jsx" class="language-jsx">function updateItem(){
      if(imgUpload.current.files.length &gt; 0){
        var formData = new FormData();
        let file = imgUpload.current.files[0];
        formData.append( 'file', file );
        formData.append( 'title', file.name );
        formData.append( 'post', itemid ); //coming from props
        let headers = {};
        headers['Content-Disposition'] = 'form-data; filename=\''+file.name+'\'';
        headers['X-WP-Nonce'] = 'your nonce here...';
        axios.post('/wp-json/wp/v2/media/?featured='+itemid,formData, headers ).then(function(resp){
          getItems(); //callback to parent's this.getItems(),
        })
      }
    }</code></pre>



<p> So basically, when we click our &#8220;Update&#8221; button, it triggers the above code. We&#8217;re checking if our DOM ref &#8220;imgUpload&#8221; has a file. The we create a <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData">FormData</a> object so we can stuff it with our file details. 3 things in particular: 1) <em>the file itself</em>, 2) <em>the title</em> and 3) the <em>post id</em> &#8211; if you&#8217;re attaching it to a particular post / page or custom post type.</p>



<p>One thing to note is the custom headers that we are using. We need &#8220;Content-Disposition&#8221; &#8211; this is to tell WordPress&#8217; API about our request, as well as &#8220;<a href="https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/">X-WP-Nonce</a>&#8220;. Since this is only going to work when we&#8217;re authenticated, and the nonce is how WordPress handles this scenario. </p>



<p>You also notice in the media endpoint, we&#8217;re passing &#8220;<strong>?featured=id</strong>&#8220;. This completely optional &#8211; and only add this if you want it to be the &#8220;<em>featured image</em>&#8220;.  You also need to add this to your <strong>functions.php</strong> file to get it to work: </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">add_filter( 'rest_prepare_attachment', 'attach_media_to_post',10,3);
function attach_media_to_post($response, $post, $request) {
    if($request-&gt;get_method()!='POST'){
        return $response;
    }
    $parameters = $request-&gt;get_params();
    if(isset($parameters['featured'])){
        set_post_thumbnail($parameters['featured'],$post-&gt;ID);
    }
    return $response;
}</code></pre>



<h3 class="wp-block-heading" id="preview-image">Preview Image</h3>



<p>Now the code above should work as is. But one thing you&#8217;ll see is when you select an image, our &#8220;img&#8221; tag remains the same as the old image &#8211; until you update it in the backend. </p>



<p>I want the user to see the file they selected before they even click &#8220;Update&#8221;.  Well if you caught it early, our input has an &#8220;onChange&#8221; event bound to &#8220;previewImage&#8221;. That&#8217;s what its about. </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">function previewImage() {
      var oFReader = new FileReader();
      oFReader.readAsDataURL(imgUpload.current.files[0]);
      oFReader.onload = function (oFREvent) {
        setImg(oFREvent.target.result);
      };
    };</code></pre>



<p>We&#8217;re using the same DOM ref &#8220;imgUpload&#8221;, and passing it into a &#8220;FileReader&#8221; object. And since our img tag is using our &#8220;img&#8221; state for it&#8217;s source, we simply call &#8220;setImg&#8221; to update that state. </p>



<p>Our selected image will show whenever we change it.</p>



<h3 class="wp-block-heading" id="improvements">Improvements</h3>



<p>This is a pretty barebones form / file upload component. There&#8217;s so much more we can do to improve it. For one, we need to restrict file types and file sizes. Maybe a nice error messaging when they select an invalid file. </p>



<p>Also, in my case, I want to delete the original image (since I don&#8217;t want it taking space in my server). So I simply add another AJAX call inside our update function (<em>inside the successful axios.post</em>). </p>



<p>Something like: </p>



<pre class="wp-block-code"><code lang="jsx" class="language-jsx">function deleteOrigImg(){
  if(origImg){
	let url = window.ONW.wp_api+'/media/'+origImg+'?force=1';
	axios.delete('/wp-json/wp/v2/media/',header).catch((err)=>{
	  handleError(context,err);
	})
  }
}</code></pre>



<p>One last thing, you also would want to see the error logs when working with WordPress REST API. Now this can be cumbersome especially when working with the out of the box endpoints. </p>



<p>This plugin <a href="https://wordpress.org/plugins/wp-rest-api-log/">REST API Log</a> provides an easy to use utility, so you can see what&#8217;s going on with your request / response. You&#8217;ll thank me (<em>or the plugin author</em>) later. </p>
<p>The post <a href="https://michaelsoriano.com/create-a-file-uploader-with-react-and-wordpress-rest-api-media/">Create a File Uploader with React and WordPress REST API (Media)</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/create-a-file-uploader-with-react-and-wordpress-rest-api-media/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
