<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CodeCadim by Brahim Hamdouni</title>
    <description>The latest articles on DEV Community by CodeCadim by Brahim Hamdouni (@barim).</description>
    <link>https://dev.to/barim</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23891%2Fd856edfd-1b5d-4489-b6cf-7a452ad888c9.png</url>
      <title>DEV Community: CodeCadim by Brahim Hamdouni</title>
      <link>https://dev.to/barim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/barim"/>
    <language>en</language>
    <item>
      <title>Displaying Images in lf with Kitty and Tmux</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Sat, 03 Jan 2026 15:45:59 +0000</pubDate>
      <link>https://dev.to/barim/displaying-images-in-lf-with-kitty-and-tmux-2971</link>
      <guid>https://dev.to/barim/displaying-images-in-lf-with-kitty-and-tmux-2971</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysj6cjsezmwgdy6gc9vx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fysj6cjsezmwgdy6gc9vx.gif" alt="Animation of lf terminal file manager displaying images" width="760" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When using lf (the terminal file manager) with Kitty and Tmux, image preview display often causes issues: graphical artifacts remain on screen when switching from one preview to another, making the interface unreadable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxiepiw0ugsx77fe0cqb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxiepiw0ugsx77fe0cqb.gif" alt="Viewing images with issues" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After several attempts, I found a solution that seems to work well. It relies on three elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;redraw&lt;/code&gt; command in lf&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;cleaner&lt;/code&gt; script&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;on-select&lt;/code&gt; event in lf&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gz0sfikyzdzqey6oa22.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gz0sfikyzdzqey6oa22.gif" alt="Viewing images without issues" width="1140" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lf Configuration
&lt;/h2&gt;

&lt;p&gt;Here's the configuration to add to your &lt;code&gt;lfrc&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set &lt;/span&gt;previewer ~/.local/bin/lfpreview
cmd on-select &amp;amp;&lt;span class="o"&gt;{{&lt;/span&gt;
  &lt;span class="nb"&gt;exec &lt;/span&gt;lf &lt;span class="nt"&gt;-remote&lt;/span&gt; &lt;span class="s1"&gt;'send redraw'&lt;/span&gt;
&lt;span class="o"&gt;}}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The preview script (&lt;code&gt;previewer&lt;/code&gt;) will be detailed later. The key element here is using &lt;code&gt;on-select&lt;/code&gt; to ask lf to redraw itself on each selection. This command performs the terminal cleanup and ensures clean preview display.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Preview Script
&lt;/h2&gt;

&lt;p&gt;Create the file &lt;code&gt;~/.local/bin/lfpreview&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
draw&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  kitten icat &lt;span class="nt"&gt;--stdin&lt;/span&gt; no &lt;span class="nt"&gt;--transfer-mode&lt;/span&gt; memory &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--place&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;h&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt;/dev/null &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/tty
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;w&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;h&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$5&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;file &lt;span class="nt"&gt;-Lb&lt;/span&gt; &lt;span class="nt"&gt;--mime-type&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
  &lt;/span&gt;image/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    draw &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;;;&lt;/span&gt;
  application/pdf&lt;span class="p"&gt;)&lt;/span&gt;
    pdftoppm &lt;span class="nt"&gt;-f&lt;/span&gt; 1 &lt;span class="nt"&gt;-singlefile&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"/tmp/lfoutput"&lt;/span&gt;
    draw &lt;span class="s2"&gt;"/tmp/lfoutput.ppm"&lt;/span&gt;
  &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    less &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

&lt;span class="nb"&gt;exit &lt;/span&gt;1 &lt;span class="c"&gt;# do not cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.local/bin/lfpreview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplified version handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images (via &lt;code&gt;kitten icat&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;PDFs (converting the first page to an image)&lt;/li&gt;
&lt;li&gt;Other files (display via &lt;code&gt;less&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Important Points
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;exit 1&lt;/code&gt; at the end of the script is crucial: it tells lf not to cache the previews. Without it, the refresh mechanism wouldn't work properly, as lf would reuse cached previews instead of redisplaying the image on each selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This configuration works well for my use case, but it may require adjustments depending on your environment. Feel free to adapt the preview script to handle other file types according to your needs.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>kitty</category>
      <category>linux</category>
      <category>lf</category>
    </item>
    <item>
      <title>CSS Hack: Let Code Blocks Break Free From Container Width</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Wed, 25 Jun 2025 13:29:03 +0000</pubDate>
      <link>https://dev.to/barim/css-hack-let-code-blocks-break-free-from-container-width-183e</link>
      <guid>https://dev.to/barim/css-hack-let-code-blocks-break-free-from-container-width-183e</guid>
      <description>&lt;p&gt;Text prose and code have fundamentally different width requirements.&lt;/p&gt;

&lt;p&gt;Prose benefits from restricted width because lines of 50-75 characters are the fastest to read, reduce eye strain and movement, and let you track easily from line end to next line start.&lt;/p&gt;

&lt;p&gt;But code blocks suffer from width restrictions. They force horizontal scrolling for long lines, break code structure and indentation, hide relationships in function calls and data structures, and make copying and understanding difficult.&lt;/p&gt;

&lt;p&gt;Here is an example of one of my previous articles with my old Hugo style:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9uzcagbnw181fl97aza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9uzcagbnw181fl97aza.png" alt="Example of text correctly wrapped but the code block is cut on the right" width="800" height="489"&gt;&lt;/a&gt;&lt;br&gt;
I need to horizontally scroll to read the rest of the parameters passed to the &lt;code&gt;load_extension&lt;/code&gt; function.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Use Hugo's &lt;code&gt;wrapperClass&lt;/code&gt; and CSS negative margin to let code blocks extend beyond text width while keeping prose properly wrapped.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Configure Hugo
&lt;/h3&gt;

&lt;p&gt;Add a CSS class to all code blocks in your &lt;code&gt;config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;markup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;highlight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;wrapperclass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;highlight full-width-content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Add the CSS Magic
&lt;/h3&gt;

&lt;p&gt;The CSS uses negative margin to break out of the parent container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.full-width-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-50vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fit-content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works&lt;/strong&gt;: The &lt;code&gt;-50vw&lt;/code&gt; (50% of viewport width) assumes your content is roughly centered and we target only the right margin because we want to stay left aligned and expand on the right. The &lt;code&gt;fit-content&lt;/code&gt; ensures the code block only expands as needed, and &lt;code&gt;position: relative&lt;/code&gt; keeps it in the document flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Result
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20zz1t76k75xhxij4vgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20zz1t76k75xhxij4vgy.png" alt="The result on the same content with text also wrapped but code block expands as necessary" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perfect! Text stays readable while code gets the space it needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fit-content&lt;/code&gt; is supported in all modern browsers&lt;/li&gt;
&lt;li&gt;On very narrow screens, you might want to add a media query to disable this behavior&lt;/li&gt;
&lt;li&gt;Ensure your main content is centered for the &lt;code&gt;-50vw&lt;/code&gt; trick to work effectively&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gohugo.io/configuration/markup/#wrapperclass" rel="noopener noreferrer"&gt;Hugo wrapperclass markup syntax highlight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/fit-content" rel="noopener noreferrer"&gt;CSS fit-content on MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>hugo</category>
      <category>hack</category>
      <category>tips</category>
    </item>
    <item>
      <title>Understanding Svelte Component Lifecycle and Reactivity</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Sat, 01 Mar 2025 21:50:19 +0000</pubDate>
      <link>https://dev.to/barim/understanding-svelte-component-lifecycle-and-reactivity-4pjf</link>
      <guid>https://dev.to/barim/understanding-svelte-component-lifecycle-and-reactivity-4pjf</guid>
      <description>&lt;p&gt;Svelte's component system features a specific approach to reactivity and component initialization. This article explores a common misconception about how props, variables, and component initialization work in Svelte.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Misconception
&lt;/h2&gt;

&lt;p&gt;Developers new to Svelte might assume that when a prop changes, the entire component script runs again, like if the component was a function and the prop a parameter: if the prop changes, the &lt;code&gt;function&lt;/code&gt; will give another result, right?&lt;br&gt;
This isn't how Svelte operates, and understanding this distinction is important for building functional applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Analyzing the Example
&lt;/h2&gt;

&lt;p&gt;The example demonstrates this concept with two components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;app.svelte&lt;/strong&gt;: A parent component with buttons to select different names&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;name.svelte&lt;/strong&gt;: A child component that receives a name prop and tracks modifications&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  The Parent Component (app.svelte)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// This shows that changing the prop does not rerun the component&lt;/span&gt;
    &lt;span class="c1"&gt;// script.&lt;/span&gt;

    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;InputName&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./name.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mila&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ali&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;    
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- This selector trigger the prop change in child component --&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#each&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/each&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- This section call the child component with the prop --&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;InputName&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The parent component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintains a list of names and a selected name state&lt;/li&gt;
&lt;li&gt;Renders buttons for each name that update the &lt;code&gt;selected&lt;/code&gt; variable&lt;/li&gt;
&lt;li&gt;Also renders the &lt;code&gt;InputName&lt;/code&gt; component with the selected name&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The Child Component (name.svelte)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// This is a simple component that implements change detection&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// this is executed only once at component mount&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

Name : &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    modified
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The child component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receives a &lt;code&gt;name&lt;/code&gt; prop using &lt;code&gt;$props()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stores the initial value in an &lt;code&gt;original&lt;/code&gt; variable&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;$derived&lt;/code&gt; to create a reactive &lt;code&gt;changed&lt;/code&gt; variable that compares current and original values&lt;/li&gt;
&lt;li&gt;Displays "modified" when the input value differs from the original&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When we click on a name and start updating the field, it shows the 'modified' indicator. This appears to work correctly.&lt;/p&gt;

&lt;p&gt;However, when we click on another name, the indicator remains visible. We can also trigger this issue by clicking on the first name without modifying it, then clicking a second name: the 'modified' indicator appears despite not updating anything.&lt;/p&gt;

&lt;p&gt;The key insight is that the component's script block runs only once when the component is initially mounted. When props change, Svelte updates the reactive dependencies without re-running the entire script.&lt;/p&gt;

&lt;p&gt;This means that &lt;code&gt;let original = name;&lt;/code&gt; is executed only once during component initialization. When the &lt;code&gt;name&lt;/code&gt; prop changes later:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;name&lt;/code&gt; value updates&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;changed&lt;/code&gt; derived value recalculates&lt;/li&gt;
&lt;li&gt;But the variable &lt;code&gt;original&lt;/code&gt; still holds the first value it received&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;To force the child component to re-execute its script when the &lt;code&gt;name&lt;/code&gt; prop changes, we use a &lt;code&gt;{#key}&lt;/code&gt; block in the parent component.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;{#key var}&lt;/code&gt; block triggers at &lt;code&gt;var&lt;/code&gt; updates by destroying and recreating the components it surrounds.&lt;/p&gt;

&lt;p&gt;For our example, we need to modify our code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- This section call the child component with the prop --&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#key&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;InputName&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;selected&lt;/code&gt; changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without &lt;code&gt;{#key}&lt;/code&gt;, the same component instance would remain and the variable &lt;code&gt;original&lt;/code&gt; would never update&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;{#key}&lt;/code&gt;, Svelte destroys and recreates the &lt;code&gt;InputName&lt;/code&gt; component, causing the script to run again and the variable &lt;code&gt;original&lt;/code&gt; to be reset&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Be aware of one-time initialization&lt;/strong&gt;: Variables assigned directly in the script block are initialized only once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use reactive declarations&lt;/strong&gt;: Leverage &lt;code&gt;$derived&lt;/code&gt; for values that need to react to prop changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand when to use &lt;code&gt;{#key}&lt;/code&gt;&lt;/strong&gt;: Use it when you need to completely reset a component state, like in our example for change detection patterns.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>svelte</category>
      <category>lifecycle</category>
      <category>reactivity</category>
    </item>
    <item>
      <title>Dynamic Svelte Components</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Mon, 16 Dec 2024 05:00:00 +0000</pubDate>
      <link>https://dev.to/barim/tutorial-dynamic-svelte-components-di1</link>
      <guid>https://dev.to/barim/tutorial-dynamic-svelte-components-di1</guid>
      <description>&lt;p&gt;Svelte offers remarkable flexibility for creating dynamic components.&lt;br&gt;
In this tutorial, we'll explore how to instantiate components on the fly&lt;br&gt;
and pass properties to them in an elegant and efficient manner.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basics of Dynamic Components
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Foo.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Bar.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt; &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;Bar&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this simple example, we import two components: Foo and Bar.&lt;/p&gt;

&lt;p&gt;We create a variable &lt;code&gt;actual&lt;/code&gt; where we'll place the current component, in this case &lt;code&gt;Foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Svelte offers a special &lt;code&gt;&amp;lt;svelte:component&amp;gt;&lt;/code&gt; tag that allows creating components on the fly.&lt;/p&gt;

&lt;p&gt;We specify in the &lt;code&gt;this&lt;/code&gt; property which component to display, in our example, &lt;code&gt;actual&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For demonstration, we add an &lt;code&gt;on:click&lt;/code&gt; event to change the component to &lt;code&gt;Bar&lt;/code&gt; by simply modifying the &lt;code&gt;actual&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Svelte takes care of displaying the component by substituting &lt;code&gt;Bar&lt;/code&gt; for &lt;code&gt;Foo&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Passing Parameters (props)
&lt;/h2&gt;

&lt;p&gt;A key point is the ability to pass parameters to dynamic components. For a classic component, you can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Foo&lt;/span&gt; &lt;span class="na"&gt;age=&lt;/span&gt;&lt;span class="s"&gt;22&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We assign the value 22 to the &lt;code&gt;age&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;For a dynamic component, it's the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt; &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Foo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;age=&lt;/span&gt;&lt;span class="s"&gt;22&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But let's imagine our second component &lt;code&gt;Bar&lt;/code&gt; accepts 2 parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Bar&lt;/span&gt; &lt;span class="na"&gt;age=&lt;/span&gt;&lt;span class="s"&gt;572&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Da Vinci"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our dynamic component should be written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt; &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Bar&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;age=&lt;/span&gt;&lt;span class="s"&gt;572&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Da Vinci"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there, we have a problem. How to manage them in the dynamic component while passing the right number of parameters?&lt;/p&gt;

&lt;p&gt;My technique involves encapsulating the component with its properties in an object and using the &lt;code&gt;spread operator&lt;/code&gt; &lt;code&gt;{...props}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, for the &lt;code&gt;Foo&lt;/code&gt; component, I would write an object &lt;code&gt;FooCmp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;FooCmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FooCmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt;
    &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cmp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;{...&lt;/span&gt;&lt;span class="na"&gt;actual.props&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the complete example, using the 2 components and a&lt;br&gt;
&lt;code&gt;flip&lt;/code&gt; function to interchange them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.svelte&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Foo.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Bar.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;FooCmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;BarCmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;572&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Da Vinci&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FooCmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;flip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cmp&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;BarCmp&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FooCmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt;
    &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cmp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;flip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;{...&lt;/span&gt;&lt;span class="na"&gt;actual.props&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each imported component will display its properties in a button and activate the &lt;code&gt;on:click&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Foo.svelte&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Foo &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Bar.svelte&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Bar &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we only pass through the &lt;code&gt;on:click&lt;/code&gt; event as it is not processed here, but at the level of the parent, the dynamic component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You can easily instantiate and manipulate components on the fly with &lt;code&gt;&amp;lt;svelte:component&amp;gt;&lt;/code&gt;. Svelte offers a simple and powerful approach to creating dynamic components. &lt;/p&gt;

&lt;p&gt;And JavaScript provides us with all the tools to work around the problem of different numbers of props per component.&lt;/p&gt;

&lt;p&gt;Don't hesitate to experiment and adapt this approach to your own needs!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>svelte</category>
      <category>dynamic</category>
      <category>components</category>
    </item>
    <item>
      <title>Change screen input programatically on Linux</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Tue, 20 Feb 2024 17:09:34 +0000</pubDate>
      <link>https://dev.to/barim/change-screen-input-programatically-on-linux-40bp</link>
      <guid>https://dev.to/barim/change-screen-input-programatically-on-linux-40bp</guid>
      <description>&lt;p&gt;I have a keyboard/mouse/screen switch to connect 2 PCs: one running Linux and one running Windows.&lt;/p&gt;

&lt;p&gt;When I connect all the ports, it works, but every time I switch to the Windows laptop, the screen reconfigures, my windows are moved, and it annoys me. The switch behaves as if I had physically unplugged/replugged the screen, and Windows feels compelled to adjust the entire layout!&lt;/p&gt;

&lt;p&gt;To fix this issue, I removed the screen connection from the switch and connected both computers to the screen's 2 sources (HDMI 1 and 2): okay, Windows doesn't rearrange all my windows when I switch to it, but now I have to switch both on the switch to get my keyboard and mouse, and I also have to manually change the screen source from HDMI 1 to 2. And vice versa when I go back to my Linux!&lt;/p&gt;

&lt;p&gt;I needed a way to switch the screen source at the same time as I switched the switch. Like, something that detects that I'm switching and voila, changes the screen source for me.&lt;/p&gt;

&lt;p&gt;Is that possible on Linux?&lt;/p&gt;

&lt;p&gt;Well yes, it is.&lt;/p&gt;

&lt;p&gt;Under Linux, we have a utility called &lt;code&gt;ddcutil&lt;/code&gt; which allows us to "talk" to the screen and send it commands (like changing the source).&lt;/p&gt;

&lt;p&gt;Here's the command to change the source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ddcutil setvcp 60 x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where x corresponds to the hexadecimal value of the source, and 60 corresponds to the source change functionality.&lt;/p&gt;

&lt;p&gt;According to the results of &lt;code&gt;ddcutil capabilities&lt;/code&gt;, I was supposed to use values 11 for HDMI 1, 12 for HDMI 2, and 0F for the display port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ddcutil capabilities
...
   Feature: 60 &lt;span class="o"&gt;(&lt;/span&gt;Input Source&lt;span class="o"&gt;)&lt;/span&gt;
      Values:
         11: HDMI-1
         12: HDMI-2
         0f: DisplayPort-1
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(I omitted other information provided by the command to focus only on the screen source)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In reality, values 11 and 12 didn't do anything. I tested all the x0f values and down, until I got a reaction from the screen.&lt;/p&gt;

&lt;p&gt;And for me, it was respectively 5 and 6 for HDMI 1 and HDMI 2.&lt;/p&gt;

&lt;p&gt;So, to switch to HDMI 1, I had to do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ddcutil setvcp 60 x5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and for HDMI 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ddcutil setvcp 60 x6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To prepare for the next steps, I create 2 script files with these commands.&lt;/p&gt;

&lt;p&gt;The first one, which I name &lt;code&gt;set-hdmi1.sh&lt;/code&gt;, is the script that changes the screen source to HDMI 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;# set input source to HDMI 1&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ddcutil setvcp 60 x5 &lt;span class="nt"&gt;--display&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't forget to make this script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x /usr/local/bin/set-hdmi1.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second one, &lt;code&gt;set-hdmi2.sh&lt;/code&gt;, is the script that changes the screen source to HDMI 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;# set input source to HDMI 2&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ddcutil setvcp 60 x6 &lt;span class="nt"&gt;--display&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;a+x /usr/local/bin/set-hdmi2.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, now that it works, I need to detect the keyboard switch.&lt;/p&gt;

&lt;p&gt;Linux allows reacting to hardware changes and launching its own actions, thanks to udev. For example, we can take action if we plug or unplug a keyboard.&lt;/p&gt;

&lt;p&gt;For this, we need to target the right hardware, and that involves finding its identifiers. The command &lt;code&gt;lsusb&lt;/code&gt; lists all devices connected via USB to my Linux, but I'm only interested in keyboards, hence the filter by the &lt;code&gt;grep&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsusb | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; key
Bus 001 Device 039: ID 04d9:0295 Holtek Semiconductor, Inc. USB-HID Keyboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important values are right after the ID:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;04d9 identifies the vendor&lt;/li&gt;
&lt;li&gt;0295 the product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, I create a new udev rules file, for example, &lt;code&gt;99-kvm.rules&lt;/code&gt; in the folder &lt;code&gt;/etc/udev/rules.d&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ACTION&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;, ATTRS&lt;span class="o"&gt;{&lt;/span&gt;idVendor&lt;span class="o"&gt;}==&lt;/span&gt;&lt;span class="s2"&gt;"04d9"&lt;/span&gt;, ATTRS&lt;span class="o"&gt;{&lt;/span&gt;idProduct&lt;span class="o"&gt;}==&lt;/span&gt;&lt;span class="s2"&gt;"0295"&lt;/span&gt;, RUN+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/bin/set-hdmi2.sh"&lt;/span&gt;
&lt;span class="nv"&gt;ACTION&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s2"&gt;"add"&lt;/span&gt;, ATTRS&lt;span class="o"&gt;{&lt;/span&gt;idVendor&lt;span class="o"&gt;}==&lt;/span&gt;&lt;span class="s2"&gt;"04d9"&lt;/span&gt;, ATTRS&lt;span class="o"&gt;{&lt;/span&gt;idProduct&lt;span class="o"&gt;}==&lt;/span&gt;&lt;span class="s2"&gt;"0295"&lt;/span&gt;, RUN+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/bin/set-hdmi1.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ACTION allows me to react, either to the removal of the keyboard (action 'remove', I switch to HDMI 2), or to its insertion (action 'add', I switch to HDMI 1).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, I identify my hardware using the values noted above, for the attributes &lt;code&gt;idVendor&lt;/code&gt; and &lt;code&gt;idProduct&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, I execute the right script.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's almost done: if we want these rules to take effect immediately (rather than at the next reboot), we can run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;udevadm control &lt;span class="nt"&gt;--reload-rules&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;udevadm trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you go! Now, I press the keyboard switch to change the screen source, and Windows stays calm! Thank you, Linux!&lt;/p&gt;

&lt;p&gt;Note: Next time I change the KVM, I'll get a basic one that only handles keyboard and mouse :-)&lt;/p&gt;

</description>
      <category>linux</category>
      <category>kvm</category>
      <category>howto</category>
    </item>
    <item>
      <title>Create tabs in Svelte</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Sun, 05 Nov 2023 22:21:59 +0000</pubDate>
      <link>https://dev.to/barim/tuto-create-tabs-in-svelte-n82</link>
      <guid>https://dev.to/barim/tuto-create-tabs-in-svelte-n82</guid>
      <description>&lt;p&gt;I often need to code some way to have multiple pages rendered in the same location : think about a configuration panel with several sub panels. The natural way to code this is using tabs.&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll use Svelte to code a simple application showing two tabs that can be easily extended to manage more tabs.&lt;/p&gt;

&lt;p&gt;As usual, let's start a new Svelte project using Esbuild, by following my previous post &lt;a href="https://dev.to/barim/tuto-setup-a-svelte-project-using-esbuild-1jmg"&gt;Setup a Svelte project using ESBuild&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also follow along on my &lt;a href="https://github.com/CodeCadim/tuto-svelte-tabs" rel="noopener noreferrer"&gt;Github page&lt;/a&gt; or on this &lt;a href="https://svelte.dev/repl/b9b5c6737f0045f3bf4693386046f356?version=4.2.2" rel="noopener noreferrer"&gt;Svelte Repl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The app.svelte will have all the logic to manage the tabs.&lt;/p&gt;

&lt;p&gt;We will add 2 more files to showcase the tabs :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;t_identity.svelte : the main tab (showed by default) &lt;/li&gt;
&lt;li&gt;t_password.svelte : another tab that will reuse our &lt;code&gt;password chooser&lt;/code&gt; from my last post &lt;a href="https://dev.to/barim/tuto-password-creation-in-svelte-1dnh"&gt;Tuto: Password Creation in Svelte&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The content of this two files is not relevant for this tutorial. Our main focus will be on the app.svelte file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./t_identity.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Password&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./t_password.svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tabs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;comp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;comp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We begin the script section by importing our two tabs : &lt;code&gt;Identity&lt;/code&gt; and &lt;code&gt;Password&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we add them to an array &lt;code&gt;tabs&lt;/code&gt;. We use a simple object with one field for the name and one field for storing the component. So if we want to add more tabs, we only need to import the component and add it to the array &lt;code&gt;tabs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, we declare a &lt;code&gt;cur&lt;/code&gt; variable to store the current tab selected : by default, we'll use the first one in the array. So &lt;code&gt;cur&lt;/code&gt; will contain an object with the name of tab and the component to show.&lt;/p&gt;

&lt;p&gt;OK, that's all for the javascript part, let's see the HTML part :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{#each tabs as tab}
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class:selected=&lt;/span&gt;&lt;span class="s"&gt;{cur&lt;/span&gt; &lt;span class="err"&gt;===&lt;/span&gt; &lt;span class="na"&gt;tab&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; (cur = tab)}&amp;gt;
        {tab.name}
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
{/each}

&lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;svelte:component&lt;/span&gt; &lt;span class="na"&gt;this=&lt;/span&gt;&lt;span class="s"&gt;{cur.comp}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We construct the tabs as buttons with a &lt;code&gt;#each&lt;/code&gt; loop, iterating on the array &lt;code&gt;tabs&lt;/code&gt; declared above :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;class:selected={cur === tab}&lt;/code&gt; will affect the class &lt;code&gt;selected&lt;/code&gt; to this button if it is the current tab (&lt;code&gt;cur&lt;/code&gt;), so we can stylize the selected tab.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;on:click={() =&amp;gt; (cur = tab)}&lt;/code&gt; will react to a click on the button by changing the current selected tab.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{tab.name}&lt;/code&gt; will be the name inside the button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important code is in the main section with the &lt;code&gt;svelte:component&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;This Svelte directive can render any component we give it. We use the fact that we stored the current tab in the &lt;code&gt;cur&lt;/code&gt; variable, precisely, the component is in the &lt;code&gt;comp&lt;/code&gt; field of our simple object.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;&amp;lt;svelte:component this={cur.comp} /&amp;gt;&lt;/code&gt; will render the tab at this location.&lt;/p&gt;

&lt;p&gt;And that's it ! We have now a way to manage tabs with Svelte, the rest is just some css styling. All source code is available on &lt;a href="https://github.com/CodeCadim/tuto-svelte-tabs" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>svelte</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Password Creation in Svelte</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Sat, 07 Oct 2023 16:49:10 +0000</pubDate>
      <link>https://dev.to/barim/tuto-password-creation-in-svelte-1dnh</link>
      <guid>https://dev.to/barim/tuto-password-creation-in-svelte-1dnh</guid>
      <description>&lt;p&gt;So, a few days ago, I saw a &lt;a href="https://youtu.be/1VZPw6VPNaU?list=PLCn4TabsxtHYEmIeSsO1lcX5OHlamuMya&amp;amp;t=589" rel="noopener noreferrer"&gt;video showing a password creation form&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdhulqpt9psp7zv0uhc2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdhulqpt9psp7zv0uhc2.gif" alt="Password chooser UI" width="421" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each time the user types anything, there is an instant validation with icons indicating which constraint is fulfilled.&lt;/p&gt;

&lt;p&gt;I thought it was a nice way to give instant feedback to the user. But can I reproduce this behaviour using Svelte ? Let's see !&lt;/p&gt;

&lt;p&gt;First, let's setup a new Svelte project using esbuild. You can follow instructions in my post &lt;a href="https://dev.to/barim/tuto-setup-a-svelte-project-using-esbuild-1jmg"&gt;Setup a Svelte project using ESBuild&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll start with one rule : the password length is 8 characters minimum. This way, we can "feel" how we can solve the problem for all the controls, setup all needed elements, without having too much in our plate. Change the &lt;code&gt;app.svelte&lt;/code&gt; file as below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="nx"&gt;customElement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;validLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;validLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;validLength&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/style&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try this, we can see that nothing happens if we type a password until it reaches 8 characters length : then the &lt;code&gt;8+&lt;/code&gt; background changes to green !&lt;/p&gt;

&lt;p&gt;Let's review the code to understand what is happening here.&lt;/p&gt;

&lt;p&gt;In the script section, we start by declaring two variables : &lt;/p&gt;

&lt;p&gt;&lt;code&gt;pass&lt;/code&gt; will contain the user input&lt;/p&gt;

&lt;p&gt;&lt;code&gt;validLength&lt;/code&gt; will indicate if the length rule is respected or not&lt;/p&gt;

&lt;p&gt;Then, we define the &lt;code&gt;check&lt;/code&gt; function : a straight forward validation of the password length.&lt;/p&gt;

&lt;p&gt;The next line is more interesting. We use the &lt;code&gt;$:&lt;/code&gt; directive to monitor any change to the password and check its validity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, every time the variable &lt;code&gt;pass&lt;/code&gt; is changed, Svelte will invoke the &lt;code&gt;check&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Below the script section, we define the html part by declaring the input field.&lt;br&gt;
It will be automatically bound to the &lt;code&gt;pass&lt;/code&gt; variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;{pass}&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, when the user enters characters in the input field, Svelte takes care of updating the &lt;code&gt;pass&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;In Svelte, we can also bind a css class to an element. Here, the span tag will be assigned the css class &lt;code&gt;valid&lt;/code&gt; only if the &lt;code&gt;validLengh&lt;/code&gt; variable is true.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class:valid=&lt;/span&gt;&lt;span class="s"&gt;{validLength}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 8+ &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;valid&lt;/code&gt; class is defined in the style section : just a green background.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.valid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is roughly all we need : the mechanism to live check the password for every keystroke and changing dynamically the style. So for the other controls, we'll apply the same logic.&lt;/p&gt;

&lt;p&gt;To check if the password contains lower and  upper case characters, we'll declare a new variable &lt;code&gt;validCase&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;validCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we'll add the html part :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class:valid=&lt;/span&gt;&lt;span class="s"&gt;{validCase}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; a..Z &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we'll complete our &lt;code&gt;check&lt;/code&gt; function to add the control :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;validCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trick here is to compare the password to its upper and lower case versions.&lt;br&gt;
The control fails if it is the same as one of them.&lt;/p&gt;

&lt;p&gt;OK, for the last control, the presence of a special character, we'll add this html :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class:valid=&lt;/span&gt;&lt;span class="s"&gt;{validSpecial}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;~&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;#&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we'll apply a regular expression in the &lt;code&gt;check&lt;/code&gt; function :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;validSpecial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will remove all non-special characters and if it remains something, then there is at least one special character.&lt;/p&gt;

&lt;p&gt;That is all, folks ! We have now a complete password creation form with live checking controls and instant feedback, with Svelte in one web component !&lt;/p&gt;

&lt;p&gt;You can find the complete code in my repo &lt;a href="https://github.com/CodeCadim/tuto-svelte-password" rel="noopener noreferrer"&gt;Tuto Svelte Password&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>svelte</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Setup a Svelte project using esbuild</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Fri, 29 Sep 2023 20:11:59 +0000</pubDate>
      <link>https://dev.to/barim/tuto-setup-a-svelte-project-using-esbuild-1jmg</link>
      <guid>https://dev.to/barim/tuto-setup-a-svelte-project-using-esbuild-1jmg</guid>
      <description>&lt;p&gt;This article will show you how to setup a new Svelte project to develop a custom tag, using esbuild, with live reloading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupih5204rerd2kwgsfy5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupih5204rerd2kwgsfy5.gif" alt="Reload Svelte app when code changes" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fisrt, why use esbuild ? Well, it's a very fast bundler that's easy to setup and I did not find a lot of tutorial about Svelte and esbuild.&lt;/p&gt;

&lt;p&gt;Next, what is a custom tag ? It's an HTML tag, like &amp;lt;pre&amp;gt; or &amp;lt;input&amp;gt; but we are in charge to define its behavior and its look, thanks to some JavaScript code. In fact, thanks to Svelte, we can define both in a single component.&lt;/p&gt;

&lt;p&gt;So, to do just that, in a new directory, we will create 4 files :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt; : defines all javascript dependencies&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;esbuild.js&lt;/code&gt; : script to launch the local server, watch files and reload Svelte&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.html&lt;/code&gt; : our main web page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.svelte&lt;/code&gt; : the Svelte custom tag component&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  package.json
&lt;/h2&gt;

&lt;p&gt;This is where we declare our dependencies. We need esbuild and its svelte plugin. Obviously, we also need Svelte.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;esbuild&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^0.19.4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;esbuild-svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^0.8.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^4.2.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install all of them, execute the npm install command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't want to create the package.json by hand, you can use this npm command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="nx"&gt;esbuild&lt;/span&gt; &lt;span class="nx"&gt;esbuild&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt; &lt;span class="nx"&gt;svelte&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But do not forget to add the line &lt;code&gt;"type": "module"&lt;/code&gt; or you'll get an error at build time.&lt;/p&gt;

&lt;h2&gt;
  
  
  esbuild.js
&lt;/h2&gt;

&lt;p&gt;The esbuild script builds, watches and reloads the Svelte application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;esbuild&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esbuild&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sveltePlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esbuild-svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;esbuild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;outdir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./build&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;sveltePlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;compilerOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;customElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;banner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new EventSource('http://127.0.0.1:8888/esbuild').addEventListener('change', () =&amp;gt; location.reload())&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;servedir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;entryPoints&lt;/code&gt; lists Svelte component main files : in this example, we only have &lt;code&gt;app.svelte&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We want to create a custom tag (web component) so we need to force the format to &lt;code&gt;esm&lt;/code&gt; and also activate the option &lt;code&gt;customElement&lt;/code&gt; in the Svelte plugin.&lt;/p&gt;

&lt;p&gt;This script will start a local server from the local directory (see &lt;code&gt;servedir&lt;/code&gt; path) on port &lt;code&gt;8888&lt;/code&gt; and watch for any changes and reload the page if any, by injecting a javascript code inside the rendered html, thanks to the &lt;code&gt;banner&lt;/code&gt; esbuild directive.&lt;/p&gt;

&lt;h2&gt;
  
  
  index.html
&lt;/h2&gt;

&lt;p&gt;Create an index.html file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"build/app.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;app-input/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that we use our web component &lt;code&gt;app-input&lt;/code&gt; as any html tag. It is that easy with Svelte. Just use a two words tag with a dash separation, so the browser knows it is a custom tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  app.svelte
&lt;/h2&gt;

&lt;p&gt;And lastly, add a file 'app.svelte' that will define our web component :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="nx"&gt;customElement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, launch your local server with :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node esbuild.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all is ok, you can connect your browser to &lt;a href="http://localhost:8888/" rel="noopener noreferrer"&gt;http://localhost:8888/&lt;/a&gt; and get the greeting message. &lt;/p&gt;

&lt;p&gt;You can update your code and see the live refresh. Happy coding !&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was cross-posted from &lt;a href="https://barim.us/post/2023-09-29-esbuild-svelte-setup/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>esbuild</category>
    </item>
    <item>
      <title>Tags in Svelte</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Wed, 26 Jul 2023 16:14:23 +0000</pubDate>
      <link>https://dev.to/barim/tutorial-tags-in-svelte-32en</link>
      <guid>https://dev.to/barim/tutorial-tags-in-svelte-32en</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdymf8118jkxn7xgw63w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdymf8118jkxn7xgw63w.gif" alt="Tags input" width="478" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to code a simple tags input component in Svelte like the animation above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An input text where I can type words.&lt;/li&gt;
&lt;li&gt;As soon as I type a comma or Enter, the input turns into a "tag".&lt;/li&gt;
&lt;li&gt;The tag appears next to the input text with a small cross to delete it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can retrieve the list of tags in an easy-to-use data structure: for example, an array of string.&lt;/p&gt;

&lt;p&gt;I'll use the &lt;a href="https://svelte.dev/repl" rel="noopener noreferrer"&gt;Svelte Repl&lt;/a&gt; for this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring possibilities
&lt;/h2&gt;

&lt;p&gt;In Svelte, &lt;code&gt;on:keydown&lt;/code&gt; triggers a function on every keypress. So I create a small piece of code to highlight this behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keydown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;keydown&lt;/code&gt; call &lt;code&gt;pressed&lt;/code&gt; function passing an &lt;code&gt;event&lt;/code&gt; object as parameter. I'm only interested in the &lt;code&gt;key&lt;/code&gt; information inside this object as it contains the key pressed by the user.&lt;/p&gt;

&lt;p&gt;Each press on the keyboard, with the cursor in the text field, will cause a display in the console.&lt;/p&gt;

&lt;p&gt;So, I can monitor the input waiting for a comma by doing a test on &lt;code&gt;key&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VIRGULE!!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keydown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've got something, now let's use that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Into the heart of the matter
&lt;/h2&gt;

&lt;p&gt;When you press comma, that's when you have a tag to add: so I take the content of the input field and I add it to my list.&lt;/p&gt;

&lt;p&gt;To see what I'm doing, I add a line with '{tags}' which will display the list of saved tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;                      &lt;span class="c1"&gt;// save tags here&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                     &lt;span class="c1"&gt;// input value&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;            &lt;span class="c1"&gt;// comma ?&lt;/span&gt;
        &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;    &lt;span class="c1"&gt;// add to the list&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                 &lt;span class="c1"&gt;// and clean input&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keydown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small problem: the comma remains in the field despite the cleaning.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;keydown&lt;/code&gt; intercepts the event before the key is taken into account by the input field. So our processing is fired before the comma is added in the &lt;code&gt;value&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Instead of &lt;code&gt;keydown&lt;/code&gt;, we will rather use &lt;code&gt;keyup&lt;/code&gt;, which will trigger our function after input is taken care. So the comma will be embedded in the value of the field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;keyup&lt;/span&gt; &lt;span class="nx"&gt;instead&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;keydown&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the comma no longer stays in the field, but is part of the 'value'.&lt;/p&gt;

&lt;p&gt;I can easily remove it before adding to the list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now my code looks like :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- here we remove comma&lt;/span&gt;
        &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before continuing, I make sure that the user does not enter anything wrong in the field. For example, a single comma or an Enter with no value should have no effect, which is not the case with the current code.&lt;/p&gt;

&lt;p&gt;So, once I remove the comma, if I have nothing left, it means I have nothing to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;              &lt;span class="c1"&gt;// &amp;lt;-- not empty ?&lt;/span&gt;
            &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;    &lt;span class="c1"&gt;// &amp;lt;-- let's work...&lt;/span&gt;
            &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't like this multi-nested level. I rather reverse the tests and exit immediately if the conditions are not met. Thus, I end up with the "good code" aligned to the left.&lt;/p&gt;

&lt;p&gt;Demonstration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh, I forgot I wanted to use also &lt;code&gt;Enter&lt;/code&gt; as a tag separator :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- Enter too&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to take care of the tags visualization : I iterate on every saved tags with the &lt;code&gt;#each&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;#each&lt;/code&gt; takes every item inside the &lt;code&gt;tags&lt;/code&gt; array and makes it available in the &lt;code&gt;t&lt;/code&gt; variable with its index in &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's use this to display each tag with an X next to it. The X is used to remove the tag.&lt;/p&gt;

&lt;p&gt;It's not a real X, it's an utf8 code that looks way more stylish 😎.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="err"&gt;⨉&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, the X is not actionable yet, so I add an anchor around it with a call to a &lt;code&gt;del&lt;/code&gt; function with the index of the tag to remove.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#del&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;⨉&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;del&lt;/code&gt; function just call &lt;a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/splice" rel="noopener noreferrer"&gt;Splice&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- remove the element at index `idx`&lt;/span&gt;
    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// &amp;lt;-- force Svelte reactivity&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The line with &lt;code&gt;tags = tags&lt;/code&gt; is used to force Svelte to refresh. This is one of the rare cases where I need to explicitly indicate to Svelte that de data model has changed.&lt;/p&gt;

&lt;p&gt;I surround each tag with a 'span' element and add a little touch of css to make it look more &lt;code&gt;taggy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#del&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;⨉&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.33&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;AD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/style&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Icing on the cake: suggestions!
&lt;/h2&gt;

&lt;p&gt;It will be nice if I can have suggestions as I type the first characters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhe81v7c2rbg8rccy5uj0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhe81v7c2rbg8rccy5uj0.gif" alt="Suggestion in tags input" width="478" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HTML let us the possibility to add suggestions in a input field, from a predefined list: &lt;code&gt;datalist&lt;/code&gt; contains the suggestions list and we use it with the &lt;code&gt;list&lt;/code&gt; property inside the input field.&lt;/p&gt;

&lt;p&gt;I define a new &lt;code&gt;tagsugg&lt;/code&gt; variable with all my suggestions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tagsugg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a real project, this list can be generated from all previously saved tags in the system.&lt;/p&gt;

&lt;p&gt;From this list, I construct the HTML &lt;code&gt;datalist&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;datalist&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag_suggestion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;tagsugg&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/datalist&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I can reference it inside the input field with the &lt;code&gt;list&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag_suggestion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;keyup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nl"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it (for the moment) !&lt;/p&gt;

&lt;p&gt;I now have an input text field that generates tags with a suggestion list !&lt;/p&gt;

&lt;p&gt;A very useful evolution is to transform this code to a web component so it can be used like a HTML tag (no pun intended 😎).&lt;/p&gt;

&lt;p&gt;You can get the complete code with comments on &lt;a href="https://svelte.dev/repl/211aabf7a4b04eae86899af96a073eba?version=4.1.1" rel="noopener noreferrer"&gt;this Repl Svelte page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was cross-posted from &lt;a href="https://barim.us/post/2023-07-26-svelte-tag-input/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>svelte</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Experiment Nebula Mesh - Part 2</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Sun, 06 Nov 2022 16:47:51 +0000</pubDate>
      <link>https://dev.to/barim/experiment-nebula-mesh-part-2-oa8</link>
      <guid>https://dev.to/barim/experiment-nebula-mesh-part-2-oa8</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/barim/experiment-nebula-mesh-part-1-46m8"&gt;In my previous post&lt;/a&gt;, I used Nebula to setup a secured network between 2 virtual machines.&lt;/p&gt;

&lt;p&gt;This time, I'll try to make a MySQL client and server communicate through a Nebula tunnel. And to make it a little bit more difficult, I'll use podman to run the client and the server in containers.&lt;/p&gt;

&lt;p&gt;I begin by restarting the virtual machines :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To restart Nebula automatically, I'm using systemd. I generate the config file for Nebula service :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; nebula.service
echo 
[Unit]
Description=Nebula service
[Service]
Type=simple
ExecStart=/opt/nebula/nebula -config /etc/nebula/config.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I push this file in the boxA temporary folder. I wish I could place it directly at his place at /etc/systemd/system but, to do that, I would need more privilege :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant upload nebula.service /tmp/ boxA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, inside boxA, I can "sudo" to place the config file in the apropriate folder :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxA &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"sudo mv /tmp/nebula.service /etc/systemd/system/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, I activate this service so it starts at boot time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxA &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"sudo systemctl enable nebula"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I do the same for boxA, beginning by copying the config file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant upload nebula.service /tmp/ boxB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I move it to the right place :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxB &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"sudo mv /tmp/nebula.service /etc/systemd/system/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finaly I activate the service :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxB &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"sudo systemctl enable nebula"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it is Podman turn to be installed, first on boxA :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxA &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"sudo apt install -y podman &amp;amp;&amp;amp; sudo reboot"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then on boxB :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxB &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"sudo apt install -y podman &amp;amp;&amp;amp; sudo reboot"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just after Podman installation, I need to reboot the virtual machines, so podman can be launched as rootless (in the user session).&lt;/p&gt;

&lt;p&gt;And because I configured Nebula as a systemd service, the tunnel will start as well.&lt;/p&gt;

&lt;p&gt;I just need to wait that the 2 virtual machines finish to boot. I can see their status with &lt;em&gt;vagrant status&lt;/em&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vagrant status

Current machine states: 

boxA                      running &lt;span class="o"&gt;(&lt;/span&gt;virtualbox&lt;span class="o"&gt;)&lt;/span&gt;
boxB                      running &lt;span class="o"&gt;(&lt;/span&gt;virtualbox&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I install the MySQL image and start the server onboxA :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxA &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"podman run -p 192.168.168.100:3306:3306 --name=db --env MYSQL_ALLOW_EMPTY_PASSWORD='true' -dt docker.io/library/mysql"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;podman run&lt;/em&gt; : I use Podman without sudo (it's one big advantage on Docker) to start the container with MySQL.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;-p 192.168.168.100:3306:3306&lt;/em&gt; : I publish the MySQL port on the Nebula IP so I can access the server from another machine on this network.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;--name=db&lt;/em&gt; : I name this container db so I can easily manipulate it later.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;--env MYSQL_ALLOW_EMPTY_PASSWORD='true'&lt;/em&gt; : I choose an empty password for this test. Of course, I would not do that in production.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;-dt docker.io/library/mysql"&lt;/em&gt;: at last I specify the MySQL image to use.&lt;/p&gt;

&lt;p&gt;To check if the server is correctly started, I can use &lt;em&gt;podman ps&lt;/em&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vagrant ssh boxA &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"podman ps"&lt;/span&gt;

CONTAINER ID  IMAGE                    COMMAND  CREATED         STATUS             PORTS                           NAMES
d6c2625aafb4  docker.io/library/mysql  mysqld   30 seconds ago  Up 30 seconds ago  192.168.168.100:3306-&amp;gt;3306/tcp  db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is working !&lt;/p&gt;

&lt;p&gt;So now, I try to access this server from boxB. I use nearly the same podman command as before, but this time I run the MySQL client :&lt;/p&gt;

&lt;p&gt;If all is ok I will be prompted by MySQL :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vagrant ssh boxB &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"podman run -ti --rm docker.io/library/mysql mysql -h192.168.168.100 -uroot"&lt;/span&gt;
Welcome to the MySQL monitor.  Commands end with &lt;span class="p"&gt;;&lt;/span&gt; or &lt;span class="se"&gt;\g&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Your MySQL connection &lt;span class="nb"&gt;id &lt;/span&gt;is 9
Server version: 8.0.29 MySQL Community Server - GPL

Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type &lt;span class="s1"&gt;'help;'&lt;/span&gt; or &lt;span class="s1"&gt;'\h'&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;help. Type &lt;span class="s1"&gt;'\c'&lt;/span&gt; to clear the current input statement.

mysql&amp;gt; show databases&lt;span class="p"&gt;;&lt;/span&gt;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows &lt;span class="k"&gt;in &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;0.01 sec&lt;span class="o"&gt;)&lt;/span&gt;

mysql&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hourra!&lt;/p&gt;

</description>
      <category>technical</category>
      <category>linux</category>
      <category>nebula</category>
      <category>vagrant</category>
    </item>
    <item>
      <title>Experiment Nebula Mesh - part 1</title>
      <dc:creator>CodeCadim by Brahim Hamdouni</dc:creator>
      <pubDate>Fri, 07 Oct 2022 16:23:05 +0000</pubDate>
      <link>https://dev.to/barim/experiment-nebula-mesh-part-1-46m8</link>
      <guid>https://dev.to/barim/experiment-nebula-mesh-part-1-46m8</guid>
      <description>&lt;p&gt;Is it possible to use the public network, namely Internet, to make 2 machines communicate securely ? And if possible something easier to install and configure than OpenVpn ?&lt;/p&gt;

&lt;p&gt;A few months ago, I heard about Nebula from &lt;a href="https://www.defined.net/nebula/"&gt;Defined&lt;/a&gt; and wanted to test it : one single binary, some certificates and as secure as it can be, that sounded promising !&lt;/p&gt;

&lt;p&gt;So here we are trying to simulate a mesh network between 2 virtual machines using &lt;a href="https://www.vagrantup.com"&gt;Vagrant&lt;/a&gt; on my Ubuntu Linux distribution 20.04 with Virtualbox already installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vagrant
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.vagrantup.com/"&gt;Vagrant&lt;/a&gt; from Hashicorp is the tool I use to manage virtual machines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; vagrant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I configure Vagrant to have 2 virtual machines with Debian 11, named respectively boxA and boxB.&lt;/p&gt;

&lt;p&gt;To make it simple, I use my host network interface to link the 2 virtual machines (so &lt;code&gt;eth0&lt;/code&gt; in my case) and use the available DHCP of my local network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; Vagrantfile
Vagrant.configure("2") do |config|
    config.vm.define "boxA" do |boxA|
        boxA.vm.box = "generic/debian11"
        boxA.vm.network "public_network", bridge: "eth0"
    end
    config.vm.define "boxB" do |boxB|
        boxB.vm.box = "generic/debian11"
        boxB.vm.network "public_network", bridge: "eth0"
    end
end
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can launch the 2 machines with a single command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nebula
&lt;/h2&gt;

&lt;p&gt;Installing nebula is as simple as downloading the binaries from &lt;a href="https://github.com/slackhq/nebula/releases"&gt;github&lt;/a&gt;. I choose &lt;code&gt;nebula-linux-amd64.tar.gz&lt;/code&gt; to comply to my configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://github.com/slackhq/nebula/releases/download/v1.6.0/nebula-linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After downloading, I uncompress the archive :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tar xf nebula-linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I now have 2 binaries : nebula and nebula-cert.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nebula&lt;/code&gt; will be copied on the 2 virtual machines. This is the main binary who will establish the bridge between the machines.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nebula-cert&lt;/code&gt; will be used to generate all needed certificates :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./nebula-cert ca &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"ACME, Inc"&lt;/span&gt;
./nebula-cert sign &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"boxA"&lt;/span&gt; &lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="s2"&gt;"192.168.168.100/24"&lt;/span&gt;
./nebula-cert sign &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"boxB"&lt;/span&gt; &lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="s2"&gt;"192.168.168.200/24"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I choose &lt;code&gt;192.168.168.*&lt;/code&gt; as my mesh network IP addresses : .100 for boxA and .200 for boxB.&lt;/p&gt;

&lt;p&gt;The results of the commands are this list of files :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ca.crt
ca.key
boxA.crt
boxA.key
boxB.crt
boxB.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make it more simple to copy the files to the virtual machines, I create a folder per machine and copy the needed files :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;boxA boxB
&lt;span class="nb"&gt;mv &lt;/span&gt;boxA.&lt;span class="k"&gt;*&lt;/span&gt; boxA &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mv &lt;/span&gt;boxB.&lt;span class="k"&gt;*&lt;/span&gt; boxB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I want to generate a Nebula configuration file, that will be common for the 2 machines. I need to get their IP addresses on my local network (those assigned by my DHCP server). I know that vagrant will use the eth1 interface inside the machines, so I use some magic shell script :&lt;/p&gt;

&lt;p&gt;First on boxA :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;boxAip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;vagrant ssh boxA &lt;span class="nt"&gt;--no-tty&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"ip address show eth1| grep 'inet ' | sed -e 's/^.*inet //' -e 's/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;.*&lt;/span&gt;&lt;span class="nv"&gt;$/&lt;/span&gt;&lt;span class="s2"&gt;/'"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'\r'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then on boxB :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;boxBip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;vagrant ssh boxB &lt;span class="nt"&gt;--no-tty&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"ip address show eth1| grep 'inet ' | sed -e 's/^.*inet //' -e 's/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;.*&lt;/span&gt;&lt;span class="nv"&gt;$/&lt;/span&gt;&lt;span class="s2"&gt;/'"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'\r'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic is that &lt;code&gt;$boxAip&lt;/code&gt; and &lt;code&gt;$boxBip&lt;/code&gt; variables now contain the wanted IPs. Let use them inside the Nebula config in the &lt;code&gt;static_host_map&lt;/code&gt; section :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; config.yml
pki:
  ca: /etc/nebula/ca.crt
  cert: /etc/nebula/host.crt
  key: /etc/nebula/host.key
static_host_map:
    "192.168.168.100": ["&lt;/span&gt;&lt;span class="nv"&gt;$boxAip&lt;/span&gt;&lt;span class="sh"&gt;:4242"]
    "192.168.168.200": ["&lt;/span&gt;&lt;span class="nv"&gt;$boxBip&lt;/span&gt;&lt;span class="sh"&gt;:4242"]
lighthouse:
  am_lighthouse: false
listen:
  host: 0.0.0.0
  port: 4242
punchy:
  punch: true
tun:
  disabled: false
  dev: nebula1
  drop_local_broadcast: false
  drop_multicast: false
  tx_queue: 500
  mtu: 1300
  routes:
  unsafe_routes:
logging:
  level: info
  format: text
firewall:
  conntrack:
    tcp_timeout: 12m
    udp_timeout: 3m
    default_timeout: 10m
    max_connections: 100000
  outbound:
    - port: any
      proto: any
      host: any
  inbound:
    - port: any
      proto: any
      host: any
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's time to configure the machines. First, let send all the files to each machine :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant upload ./boxA /tmp/ boxA
vagrant upload ./boxB /tmp/ boxB
vagrant upload ca.crt /tmp/ boxA
vagrant upload ca.crt /tmp/ boxB
vagrant upload config.yml /tmp/ boxA
vagrant upload config.yml /tmp/ boxB
vagrant upload nebula /tmp/ boxA
vagrant upload nebula /tmp/ boxB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I ssh in each machine and continue the configuration :&lt;/p&gt;

&lt;p&gt;First, boxA :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside boxA, I move the files in their respective location and finally launch Nebula in the background before quitting boxA :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /etc/nebula
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/config.yml /etc/nebula/config.yml
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/ca.crt /etc/nebula/ca.crt
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/boxA.crt /etc/nebula/host.crt
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/boxA.key /etc/nebula/host.key
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /opt/nebula 
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/nebula /opt/nebula/
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /opt/nebula/nebula
&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/nebula
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./nebula &lt;span class="nt"&gt;-config&lt;/span&gt; /etc/nebula/config.yml &amp;amp;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's configure boxB,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I move all files and launch Nebula :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /etc/nebula
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/config.yml /etc/nebula/config.yml
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/ca.crt /etc/nebula/ca.crt
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/boxB.crt /etc/nebula/host.crt
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/boxB.key /etc/nebula/host.key
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /opt/nebula 
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/nebula /opt/nebula/
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /opt/nebula/nebula
&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/nebula
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./nebula &lt;span class="nt"&gt;-config&lt;/span&gt; /etc/nebula/config.yml &amp;amp;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, at this moment, I have 2 virtual machines, with a Nebula network between them. How am I going to verify that it is really working ?&lt;/p&gt;

&lt;p&gt;Well if I can ping boxB from boxA, it will mean that all is ok, so let's found out :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxA &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"ping 192.168.168.200"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hourra ! It is working. Of course, I can do it on the other side :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vagrant ssh boxB &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"ping 192.168.168.100"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all folks for part 1 !&lt;/p&gt;

&lt;p&gt;Next, I'll try to use this configuration to execute a MySQL server on one machine, and access it from a MySQL client on the other machine. And to make it a little more difficult, I'll use Podman as the container engine to execute this client and server. &lt;/p&gt;

&lt;p&gt;See &lt;a href="https://dev.to/barim/experiment-nebula-mesh-part-2-oa8"&gt;Part 2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>technical</category>
      <category>linux</category>
      <category>nebula</category>
      <category>vagrant</category>
    </item>
  </channel>
</rss>
