<?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>Michael Soriano</title>
	<atom:link href="https://michaelsoriano.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://michaelsoriano.com/</link>
	<description>I turn code into captivating user experiences for the web</description>
	<lastBuildDate>Mon, 09 Dec 2024 18:32:18 +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>Modern CSS Features Every Front-End Dev Should Know</title>
		<link>https://michaelsoriano.com/modern-css-features-every-front-end-dev-should-know/</link>
					<comments>https://michaelsoriano.com/modern-css-features-every-front-end-dev-should-know/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 09 Dec 2024 18:32:18 +0000</pubDate>
				<category><![CDATA[CSS]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=8165</guid>

					<description><![CDATA[<p>Ready to level up your CSS game? Let&#8217;s dive into some modern CSS features that are changing the way we style our websites. Whether you&#8217;re a seasoned pro or just starting out, these tricks will add some serious firepower to your toolkit. 1. CSS Subgrid: Nested Grids, Unleashed Remember when aligning nested grid items was [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/modern-css-features-every-front-end-dev-should-know/">Modern CSS Features Every Front-End Dev Should Know</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ready to level up your CSS game? Let&#8217;s dive into some <strong>modern CSS features</strong> that are changing the way we style our websites. Whether you&#8217;re a seasoned pro or just starting out, these tricks will add some serious firepower to your toolkit.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="706" height="372" src="https://michaelsoriano.com/wp-content/uploads/2024/12/image.png" alt="" class="wp-image-8193"/></figure></div>


<h2 class="wp-block-heading">1. CSS Subgrid: Nested Grids, Unleashed</h2>



<p>Remember when aligning nested grid items was a pain? <strong>CSS Subgrid</strong> is here to save the day. It allows child elements to align with the parent grid, creating more complex and flexible layouts.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.parent-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.child-grid {
  display: grid;
  grid-template-columns: subgrid;
}</code></pre>



<p>With this setup, your child grid items will align perfectly with the parent grid columns. No more manual calculations or nested grid headaches!</p>



<h2 class="wp-block-heading">2. CSS Scroll Snap: Smooth Scrolling, Simplified</h2>



<p>Want to create that slick, app-like scrolling experience? <strong>CSS Scroll Snap</strong> has got you covered. It&#8217;s perfect for image galleries, paginated content, or any situation where you want controlled, smooth scrolling.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.container {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
}

.item {
  scroll-snap-align: start;
}</code></pre>



<p>Just like that, you&#8217;ve got a smooth-scrolling container. Your users will thank you!</p>



<h2 class="wp-block-heading">3. CSS Backdrop Filter: Blurring the Lines</h2>



<p>Ever wanted to apply cool effects to the area behind an element? <strong>CSS Backdrop Filter</strong> lets you do just that. Blur, color shift, or add other graphical effects to create stunning visual designs.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.overlay {
  backdrop-filter: blur(10px) brightness(80%);
}</code></pre>



<p>This simple line can transform a plain overlay into a captivating visual element. The possibilities are endless!</p>



<h2 class="wp-block-heading">4. CSS Custom Properties: Variables Get a Makeover</h2>



<p>While not brand new, <strong>CSS Custom Properties</strong> (also known as CSS Variables) have gained wide support and are a game-changer for creating dynamic, reusable styles.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">:root {
  --main-color: #3498db;
}

.button {
  background-color: var(--main-color);
}</code></pre>



<p>With this setup, changing your site&#8217;s color scheme becomes a breeze. One change at the root, and it propagates throughout your entire site!</p>



<h2 class="wp-block-heading">5. CSS @property: Taking Control of Custom Properties</h2>



<p>Want more control over your custom properties? The <strong>@property</strong> rule lets you define the type, inheritance, and initial value of your CSS custom properties.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">@property --gradient-angle {
  syntax: '&lt;angle&gt;';
  initial-value: 0deg;
  inherits: false;
}</code></pre>



<p>This level of control opens up new possibilities for animations and dynamic styling that were previously difficult or impossible.</p>



<h2 class="wp-block-heading">6. CSS Container Queries: Responsive Design 2.0</h2>



<p>Last but certainly not least, we have <strong>CSS Container Queries</strong>. This feature is set to revolutionize responsive design by allowing you to style elements based on the size of a containing element, not just the viewport.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.container {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 2fr 1fr;
  }
}</code></pre>



<p>This approach allows for truly modular design, where components can adapt to their container regardless of where they&#8217;re placed in the layout.</p>



<h2 class="wp-block-heading">Wrapping Up</h2>



<p>These <strong>modern CSS features</strong> are just the tip of the iceberg. They represent a shift towards more powerful, flexible, and intuitive web design. By incorporating these techniques into your workflow, you&#8217;ll be able to create more dynamic, responsive, and visually appealing websites.</p>



<p>Remember, the key to mastering these features is practice. So go ahead, experiment with them in your next project. Your future self (and your users) will thank you!</p>



<p>Keep coding, keep learning, and keep pushing the boundaries of what&#8217;s possible with CSS. The future of web design is looking brighter than ever!</p>
<p>The post <a href="https://michaelsoriano.com/modern-css-features-every-front-end-dev-should-know/">Modern CSS Features Every Front-End Dev Should Know</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/modern-css-features-every-front-end-dev-should-know/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>The Hidden UX: Mastering URL Design for Better User Experience</title>
		<link>https://michaelsoriano.com/the-hidden-ux-mastering-url-design-for-better-user-experience/</link>
					<comments>https://michaelsoriano.com/the-hidden-ux-mastering-url-design-for-better-user-experience/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Thu, 21 Nov 2024 12:59:59 +0000</pubDate>
				<category><![CDATA[Design & UX]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=8176</guid>

					<description><![CDATA[<p>When you think of User Experience (UX), what comes to mind? Most likely, it&#8217;s the visible elements within an application window &#8211; what you can see, click, or swipe. But there&#8217;s a crucial aspect of UX that often goes unnoticed: the URL in your address bar. Far from being a mere technicality, the URL is [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/the-hidden-ux-mastering-url-design-for-better-user-experience/">The Hidden UX: Mastering URL Design for Better User Experience</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>When you think of User Experience (UX), what comes to mind? Most likely, it&#8217;s the visible elements within an application window &#8211; what you can see, click, or swipe. But there&#8217;s a crucial aspect of UX that often goes unnoticed: the URL in your address bar. Far from being a mere technicality, the URL is an extension of your application and, arguably, its most important part.</p>



<p>While we&#8217;re all familiar with the SEO benefits of a well-structured URL, this article focuses on something different: the <em>user experience</em>. A thoughtfully designed URL structure can provide users with a sense of cohesiveness, demonstrating that your application is well-organized and carefully considered.</p>



<p>And here&#8217;s the kicker: even if SEO isn&#8217;t a priority for your web application, you&#8217;re not off the hook. Good URL design is for everyone, because it directly impacts how users interact with and perceive your site.</p>



<p>As Richard Branson aptly put it, &#8220;<em>When making experiences, attention to detail matters</em>.&#8221;</p>



<h2 class="wp-block-heading">Anatomy of a URL</h2>



<p>Before we dive into best practices, let&#8217;s break down the components of a URL:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="619" height="243" src="https://michaelsoriano.com/wp-content/uploads/2022/06/image-1.png" alt="Elements of a URL" class="wp-image-7644" srcset="https://michaelsoriano.com/wp-content/uploads/2022/06/image-1.png 619w, https://michaelsoriano.com/wp-content/uploads/2022/06/image-1-300x118.png 300w" sizes="(max-width: 619px) 100vw, 619px" /></figure>



<p>While the &#8220;https://&#8221; protocol is pretty much a given these days, every other part of the URL deserves your attention. Even if you only have control over the path and beyond, understanding the entire structure will help you make better design decisions.</p>



<p>Don&#8217;t forget about the optional elements:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="686" height="300" src="https://michaelsoriano.com/wp-content/uploads/2022/06/image.png" alt="Querystrings and Hash/Anchor" class="wp-image-7647" srcset="https://michaelsoriano.com/wp-content/uploads/2022/06/image.png 686w, https://michaelsoriano.com/wp-content/uploads/2022/06/image-300x131.png 300w" sizes="(max-width: 686px) 100vw, 686px" /></figure>



<p>Towards the end, you might see a question mark (?) or a hash (#) and some characters after it. We&#8217;ll talk about these as well.</p>



<p>But first, lets look at the Golden Rules:</p>



<h2 class="wp-block-heading">The Golden Rules of UX-Friendly URLs</h2>



<p>When crafting URLs, keep these three cardinal rules in mind:</p>



<ol class="wp-block-list">
<li><strong>Brevity is key</strong>: Shorter URLs are easier to remember, share, and type.</li>



<li><strong>Readability matters</strong>: If a human can&#8217;t easily understand your URL, it&#8217;s time to rethink it.</li>



<li><strong>Make it meaningful</strong>: Each element should convey purpose and context.</li>
</ol>



<p>These rules aren&#8217;t set in stone, but they provide a solid foundation for creating user-friendly URLs. </p>



<p>Let&#8217;s explore how to apply them.</p>



<h2 class="wp-block-heading">Mastering the Domain Game</h2>



<p>Your domain is your digital real estate &#8211; make it count. For our examples, we&#8217;ll use the fictional company &#8220;Acme&#8221;:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="308" height="154" src="https://michaelsoriano.com/wp-content/uploads/2022/06/image-3.png" alt="" class="wp-image-7656" srcset="https://michaelsoriano.com/wp-content/uploads/2022/06/image-3.png 308w, https://michaelsoriano.com/wp-content/uploads/2022/06/image-3-300x150.png 300w" sizes="(max-width: 308px) 100vw, 308px" /></figure>



<p>Other options:</p>



<ul class="wp-block-list">
<li>acme.net</li>



<li>acme.io</li>



<li>acme.app</li>
</ul>



<p>Notice how these domains are short, readable, and meaningful. With the proliferation of top-level domains, you have more flexibility than ever to create a memorable web address. In addition, with the wider array of available TLD&#8217;s (the <em>.com</em> or <em>.net</em> part of the domain) &#8211; you can make use of this as part of how you structure your organization. For example, &#8220;.<em>com</em>&#8221; will be for your public website, &#8220;<em>.app</em>&#8221; will be the &#8220;<em>application</em>&#8221; side. Otherwise, we can use subdomains:</p>



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



<p>While subdomains can break the brevity rule, they&#8217;re almost always necessary. Subdomains are also good since you only maintain one main domain. Still, use them judiciously for distinct sections of your site. </p>



<figure class="wp-block-image size-full"><img decoding="async" width="455" height="283" src="https://michaelsoriano.com/wp-content/uploads/2022/06/image-2.png" alt="Subdomains - good" class="wp-image-7655" srcset="https://michaelsoriano.com/wp-content/uploads/2022/06/image-2.png 455w, https://michaelsoriano.com/wp-content/uploads/2022/06/image-2-300x187.png 300w" sizes="(max-width: 455px) 100vw, 455px" /></figure>



<p>Remember: one subdomain level is usually sufficient. Anything deeper risks confusion and violates our first two rules.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="434" height="194" src="https://michaelsoriano.com/wp-content/uploads/2022/06/image-5.png" alt="subdomain bad" class="wp-image-7662" srcset="https://michaelsoriano.com/wp-content/uploads/2022/06/image-5.png 434w, https://michaelsoriano.com/wp-content/uploads/2022/06/image-5-300x134.png 300w" sizes="(max-width: 434px) 100vw, 434px" /></figure>



<p>In addition, having too many &#8220;.&#8221; (dots) is just annoying &#8211; agree?</p>



<h3 class="wp-block-heading">SaaS URL Strategies</h3>



<p>For SaaS products, consider offering &#8220;vanity&#8221; URLs that combine your main domain with a subdomain:</p>



<p>Good examples:</p>



<ul class="wp-block-list">
<li>acme.workday.com</li>



<li>acme.salesforce.com</li>
</ul>



<p>Avoid confusing structures like:</p>



<ul class="wp-block-list">
<li>na111.salesforce.com</li>



<li>emea.online.salesforce.com</li>
</ul>



<p>The goal is to create URLs that users can easily type and understand at a glance.</p>



<h2 class="wp-block-heading">Perfecting the Path</h2>



<p>The path is where you have the most control over your URL structure. Here are some best practices to keep in mind:</p>



<ol class="wp-block-list">
<li><strong>Use hyphens as separators</strong>: <code>/user-profile</code> is more readable than <code>/user_profile</code> or <code>/userProfile</code>.</li>



<li><strong>Create logical hierarchies</strong>: <code>/products/electronics/smartphones</code> tells a clear story.</li>



<li><strong>Stick to lowercase</strong>: <code>/blog/latest-posts</code> is less error-prone than <code>/Blog/Latest-Posts</code>.</li>



<li><strong>Eliminate unnecessary words</strong>: <code>/about</code> is cleaner than <code>/about-us</code>.</li>



<li><strong>Use nouns for resources</strong>: <code>/users/123</code> is more RESTful than <code>/get-user/123</code>.</li>
</ol>



<h2 class="wp-block-heading">Slash, Hash, or Query: Choosing Your Weapon</h2>



<p>Each URL component has its purpose:</p>



<ul class="wp-block-list">
<li><strong>Slashes (/)</strong>: Perfect for hierarchical structure and main navigation.</li>



<li><strong>Hashes (#)</strong>: Ideal for anchors within a page or client-side routing in SPAs.</li>



<li><strong>Query parameters (?)</strong>: Best for optional or variable parameters.</li>
</ul>



<p>Choose wisely based on your application&#8217;s architecture and the nature of the information you&#8217;re conveying. </p>



<h2 class="wp-block-heading">Navigating the Browser Landscape</h2>



<p>Good URL design supports intuitive browser navigation. Users should be able to use back and forward buttons effectively and understand their location within your site&#8217;s hierarchy just by glancing at the URL.</p>



<p>For Single Page Applications (SPAs), this means implementing proper routing and history management. Tools like React Router or Vue Router can help maintain a navigable history stack, even with dynamically loaded content.</p>



<h2 class="wp-block-heading">The Art of Bookmarkability</h2>



<p>One often overlooked aspect of URL design is bookmarkability. Users should be able to bookmark any page on your site and return to the exact same state later. This means:</p>



<ol class="wp-block-list">
<li>Avoiding session-specific information in URLs</li>



<li>Using proper routing in SPAs to capture the application state</li>



<li>Ensuring dynamically loaded content has a corresponding URL state</li>
</ol>



<h2 class="wp-block-heading">Conclusion: Small Details, Big Impact</h2>



<p>While it&#8217;s easy to overlook URLs in the grand scheme of UX design, they play a crucial role in creating a cohesive, intuitive, and user-friendly web experience. By applying these principles and paying attention to the details of your URL structure, you&#8217;ll create a stronger, more navigable, and more professional web presence.</p>



<p>Remember, your URL is often the first point of interaction between your user and your application – make it count! Your users may not consciously notice good URL design, but they&#8217;ll certainly appreciate the improved usability it brings. In the world of UX, sometimes the smallest details make the biggest difference.</p>
<p>The post <a href="https://michaelsoriano.com/the-hidden-ux-mastering-url-design-for-better-user-experience/">The Hidden UX: Mastering URL Design for Better User Experience</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/the-hidden-ux-mastering-url-design-for-better-user-experience/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<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 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>Laracasts.com: a gold mine of content for Web Developers</title>
		<link>https://michaelsoriano.com/laracasts-com-a-gold-mine-of-content-for-web-developers/</link>
					<comments>https://michaelsoriano.com/laracasts-com-a-gold-mine-of-content-for-web-developers/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 08 Jul 2024 18:26:44 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=8127</guid>

					<description><![CDATA[<p>I&#8217;ve been a Software Engineer for many years. And for the past few, JavaScript has been emerging with newer, better and shinier things. But like many others, I&#8217;ve been having a little bit of JavaScript fatigue. Lately, I&#8217;ve been looking to other frameworks with more stability. Something that I rely on &#8211; that will work [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/laracasts-com-a-gold-mine-of-content-for-web-developers/">Laracasts.com: a gold mine of content for Web Developers</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve been a Software Engineer for many years. And for the past few, JavaScript has been emerging with newer, better and shinier things. But like many others, I&#8217;ve been having a little bit of <a href="https://auth0.com/blog/how-to-manage-javascript-fatigue/">JavaScript fatigue</a>. Lately, I&#8217;ve been looking to other frameworks with more stability. Something that I rely on &#8211; that will work for years to come. </p>



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



<p>PHP was my first real programming language. And Laravel is built with PHP. I&#8217;ve always heard of Laravel, but never used it. I&#8217;ve watched many videos about how good it is, installed a sample application &#8211; and was sold. </p>



<p>I want to learn more &#8211; so I signed up for <a href="https://laracasts.com/referral/Michaelsoriano" rel="nofollow">Laracasts</a>. If you’re a web developer, suffering from JS Fatigue, and want to learn Laravel &#8211; Laracasts.com is like striking gold.</p>



<figure class="wp-block-image size-large"><a href="https://laracasts.com/referral/Michaelsoriano" rel="nofollow"><img decoding="async" width="1024" height="584" src="https://michaelsoriano.com/wp-content/uploads/2024/07/image-1024x584.jpg" alt="Power to the modern developer" class="wp-image-8140" srcset="https://michaelsoriano.com/wp-content/uploads/2024/07/image-1024x584.jpg 1024w, https://michaelsoriano.com/wp-content/uploads/2024/07/image-300x171.jpg 300w, https://michaelsoriano.com/wp-content/uploads/2024/07/image-768x438.jpg 768w, https://michaelsoriano.com/wp-content/uploads/2024/07/image.jpg 1117w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>Top-notch tutorials and lessons. I, for one have signed up on many premium bootcamps and tutorial websites. So far, Laracasts is the best I&#8217;ve seen. Let me explain. </p>



<h3 class="wp-block-heading"><strong>Talented Instructors &#8211; <strong>Jeffrey Way</strong></strong></h3>



<p>Jeffrey Way, the main instructor, has a unique gift for making complex topics easy to understand. His explanations are clear and straightforward, making even the most daunting subjects feel manageable. He has a way of teaching &#8211; that reminds me of how elementary school was &#8211; but for a modern, experienced developer. </p>



<p>Plus, he presents everything in such an engaging way that you’re hooked from the first video. I especially like how he organizes his content &#8211; from inception to conception. Jeffrey Way is as good as it gets.</p>



<p>In addition, I&#8217;ve seen a couple of series on Inertia, React and APIs &#8211; and the instructors were also pretty good. Not the same style as Jeffrey &#8211; but good nonetheless. </p>



<h3 class="wp-block-heading"><strong>Structured Learning Paths for Laravel and More</strong></h3>



<p>One of my favorite features is the structured learning paths. These pathways are like having a personal guide through the vast world of web development. They ensure you build a solid foundation before moving on to more advanced topics. This is incredibly helpful if you’re new to coding or trying to learn a new framework like Laravel.</p>



<p>There is also small bits of lessons called &#8220;<strong><a href="https://laracasts.com/referral/Michaelsoriano" rel="nofollow">Larabits</a></strong>&#8220;. These are quick how-to videos, that&#8217;s not necessarily tied to a learning path. Just fast paced watch and go type of tut. </p>



<h3 class="wp-block-heading"><strong>Supportive Community</strong></h3>



<p>The community at Laracasts is fantastic. The forums are buzzing with activity and full of people ready to help out with any questions you might have about Laravel tutorials or other topics. It&#8217;s great to be part of a community where you can share knowledge and get support from fellow learners. </p>



<p>Plus, Jeffrey Way is actively involved, which adds a personal touch to the experience.</p>



<p>In addition, each video has a comments area &#8211; where you can post comments &#8211; and the community is also very responsive. This helps when you&#8217;re stuck in part of the video, commenting will get you &#8220;unstuck&#8221; real quick.</p>



<h3 class="wp-block-heading"><strong>Diverse Range of Topics Beyond Laravel</strong></h3>



<p>While Laracasts is famous for its Laravel tutorials, it doesn’t stop there. The site offers in-depth tutorials on JavaScript, Vue, React, testing, and general web development practices. As mentioned above &#8211; the instructors and the way they teach the course is paramount. So the topics can vary &#8211; and you get the same high quality tutorial &#8211; which is a good deal.</p>



<figure class="wp-block-image size-full"><a href="https://laracasts.com/referral/Michaelsoriano" rel="nofollow"><img decoding="async" width="851" height="810" src="https://michaelsoriano.com/wp-content/uploads/2024/07/image-1.png" alt="Laracasts Topics" class="wp-image-8137" srcset="https://michaelsoriano.com/wp-content/uploads/2024/07/image-1.png 851w, https://michaelsoriano.com/wp-content/uploads/2024/07/image-1-300x286.png 300w, https://michaelsoriano.com/wp-content/uploads/2024/07/image-1-768x731.png 768w" sizes="(max-width: 851px) 100vw, 851px" /></a></figure>



<p>So whether you&#8217;re looking to dive deep into a specific framework or broaden your overall skill set, Laracasts has you covered. I was even surprised to see GraphQL, CSS and Webpack in there &#8211; its not just backend stuff!</p>



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



<p>Laracasts.com is a must-have resource for anyone serious about web development, especially if you want to master Laravel tutorials. Its combination of excellent instructors that produce high-quality content. The strong community that you become part of &#8211; is truly indispensable. You get to learn everything about Laravel, but also other skills as well. In addition, the library is constantly updated, with new paths, technologies and lessons.  </p>



<p>Whether you’re aiming to become a Laravel expert, improve your JavaScript skills, or just become a better developer overall, <a href="https://laracasts.com/referral/Michaelsoriano" rel="nofollow">Laracasts</a> is an investment you won’t regret.</p>
<p>The post <a href="https://michaelsoriano.com/laracasts-com-a-gold-mine-of-content-for-web-developers/">Laracasts.com: a gold mine of content for Web Developers</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/laracasts-com-a-gold-mine-of-content-for-web-developers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Import a .fig file for Editing in Figma</title>
		<link>https://michaelsoriano.com/how-to-import-a-fig-file-to-figma/</link>
					<comments>https://michaelsoriano.com/how-to-import-a-fig-file-to-figma/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Tue, 07 May 2024 02:09:26 +0000</pubDate>
				<category><![CDATA[Design & UX]]></category>
		<guid isPermaLink="false">https://michaelsoriano.com/?p=8087</guid>

					<description><![CDATA[<p>Ah &#8211; so you&#8217;ve got yourself a .fig file and you&#8217;re wondering what to do with it. Did you know that .fig files are easy to use templates that is primed for further tinkering and collaboration? Whether you&#8217;re a seasoned designer or just dipping your toes into the world of digital design, importing your .fig [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/how-to-import-a-fig-file-to-figma/">How to Import a .fig file for Editing in Figma</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ah &#8211; so you&#8217;ve got yourself a <code>.fig</code> file and you&#8217;re wondering what to do with it. Did you know that <code>.fig</code> files are easy to use templates that is primed for further tinkering and collaboration? Whether you&#8217;re a seasoned designer or just dipping your toes into the world of digital design, importing your <code>.fig</code> file is a breeze with Figma&#8217;s intuitive interface.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1023" height="489" src="https://michaelsoriano.com/wp-content/uploads/2024/05/image-4.png" alt="" class="wp-image-8091" srcset="https://michaelsoriano.com/wp-content/uploads/2024/05/image-4.png 1023w, https://michaelsoriano.com/wp-content/uploads/2024/05/image-4-300x143.png 300w, https://michaelsoriano.com/wp-content/uploads/2024/05/image-4-768x367.png 768w" sizes="(max-width: 1023px) 100vw, 1023px" /></figure>



<p>In this guide, we&#8217;ll walk you through the process step by step, ensuring you seamlessly integrate your <code>.fig</code> file into your Figma workspace. So, grab your creativity and let&#8217;s dive in!</p>



<h3 class="wp-block-heading">Step 1: Start Figma </h3>



<p>Start by opening Figma. If you don&#8217;t have an account, sign up for one—it&#8217;s free! Create or Open Your Project: Once you&#8217;re in Figma, either start a new project or open an existing one where you want to import your <code>.fig</code> file.</p>



<p><strong>Find the Import Option:</strong> Look for the &#8220;File&#8221; menu at the top-left corner of the screen.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="501" height="322" src="https://michaelsoriano.com/wp-content/uploads/2024/05/image-1.png" alt="Import button" class="wp-image-8088" srcset="https://michaelsoriano.com/wp-content/uploads/2024/05/image-1.png 501w, https://michaelsoriano.com/wp-content/uploads/2024/05/image-1-300x193.png 300w" sizes="(max-width: 501px) 100vw, 501px" /></figure></div>


<h3 class="wp-block-heading">Step 2: Select File</h3>



<p>Choose &#8220;From your computer&#8221; from the modal pop up. This will trigger your machine&#8217;s file navigator and allow you to select your <code>.fig</code> file. The &#8220;From Jamboard&#8221; option is also useful &#8211; if your <code>.fig</code> file is shared via Google Drive. </p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="623" height="410" src="https://michaelsoriano.com/wp-content/uploads/2024/05/image-2.png" alt="File navigator" class="wp-image-8089" srcset="https://michaelsoriano.com/wp-content/uploads/2024/05/image-2.png 623w, https://michaelsoriano.com/wp-content/uploads/2024/05/image-2-300x197.png 300w" sizes="(max-width: 623px) 100vw, 623px" /></figure></div>


<p>Once you&#8217;ve selected it, click &#8220;Open&#8221;. Depending on the size of the file, you might have to wait a few moments. Figma can sometimes take a few seconds to process the file. Patience my friend.</p>



<h3 class="wp-block-heading">Step 3: Start Editing</h3>



<p>Once the import is done, you&#8217;ll see your <code>.fig</code> file in your project. It might be a new file or a new page/tab in an existing file. Now you&#8217;re ready to edit the file. You can now edit your imported <code>.fig</code> file in Figma, just like any other project.</p>



<p>Don&#8217;t forget: Figma saves your changes automatically, but you can always save a version manually if you like.</p>
<p>The post <a href="https://michaelsoriano.com/how-to-import-a-fig-file-to-figma/">How to Import a .fig file for Editing in Figma</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/how-to-import-a-fig-file-to-figma/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>
	</channel>
</rss>
